<commit_before>var fs = require('fs');
var path = require('path');
var browserify = require('browserify');
var babelify = require('babelify');
var envify = require('envify/custom');
var CombinedStream = require('combined-stream');
var argv = require('minimist')(process.argv.slice(2));

var packageJSON = JSON.parse(fs.readFileSync('./package.json'));

var banner = '' +
'/**\n' +
'* AutoLayout.js is licensed under the MIT license. If a copy of the\n' +
'* MIT-license was not distributed with this file, You can obtain one at:\n' +
'* http://opensource.org/licenses/mit-license.html.\n' +
'*\n' +
'* @author: Hein Rutjes (IjzerenHein)\n' +
'* @license MIT\n' +
'* @copyright Gloey Apps, 2015\n' +
'*\n' +
'* @library autolayout.js\n' +
'* @version ' + packageJSON.version + '\n' +
'*/\n';
var cassowaryBanner = '' +
'/**\n' +
'* Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org)\n' +
'* Parts Copyright (C) Copyright (C) 1998-2000 Greg J. Badros\n' +
'*\n' +
'* Use of this source code is governed by the LGPL, which can be found in the\n' +
'* COPYING.LGPL file.\n' +
'*/\n';
var kiwiBanner = '' +
'/*-----------------------------------------------------------------------------\n' +
'| Kiwi (TypeScript version)\n' +
'|\n' +
'| Copyright (c) 2014, Nucleic Development Team.\n' +
'|\n' +
'| Distributed under the terms of the Modified BSD License.\n' +
'|\n' +
'| The full license is in the file COPYING.txt, distributed with this software.\n' +
'|----------------------------------------------------------------------------*/\n';

function dist(kiwi, minify) {
    var input = CombinedStream.create();
    input.append(!kiwi ? 'var c = require(\'cassowary/bin/c\')\n' : 'var kiwi = require(\'kiwi/ts/bin/kiwi\')\n');
    input.append(fs.createReadStream('./tmp/autolayout.es6'));
    var output = fs.createWriteStream('dist/autolayout' + (kiwi ? '.kiwi' : '') + (minify ? '.min' : '') + '.js');
    output.write(banner);
    output.write(kiwi ? kiwiBanner : cassowaryBanner);
    var b = browserify(input, {
        debug: minify,
        standalone: 'AutoLayout',
        banner: banner
    });
    b.transform(babelify.configure({
        compact: false
    }));
    b.transform(envify({
        CASSOWARYJS: !kiwi
    }));
    if (minify) {
        b.plugin('minifyify', {
            map: 'autolayout.min.map',
            output: 'dist/autolayout.min.map',
            compressPath: function(p) {
                if (p.indexOf('kiwi') >= 0) {
                    return path.relative('node_modules/kiwi/ts/bin', p);
                }
                else {
                    return path.relative('tmp', p);
                }
            }
        });
    }
    b.bundle().on('error', function(err) {
        console.log('Error : ' + err.message);
    }).pipe(output);
}
dist(false, false);
if (!argv.fast) {
    dist(false, true);
    dist(true, false);
}
//dist(true, true);
<commit_msg>Fixed build of kiwi version (caused by babel upgrade).<commit_after>var fs = require('fs');
var path = require('path');
var browserify = require('browserify');
var babelify = require('babelify');
var envify = require('envify/custom');
var CombinedStream = require('combined-stream');
var argv = require('minimist')(process.argv.slice(2));

var packageJSON = JSON.parse(fs.readFileSync('./package.json'));

var banner = '' +
'/**\n' +
'* AutoLayout.js is licensed under the MIT license. If a copy of the\n' +
'* MIT-license was not distributed with this file, You can obtain one at:\n' +
'* http://opensource.org/licenses/mit-license.html.\n' +
'*\n' +
'* @author: Hein Rutjes (IjzerenHein)\n' +
'* @license MIT\n' +
'* @copyright Gloey Apps, 2016\n' +
'*\n' +
'* @library autolayout.js\n' +
'* @version ' + packageJSON.version + '\n' +
'*/\n';
var cassowaryBanner = '' +
'/**\n' +
'* Parts Copyright (C) 2011-2012, Alex Russell (slightlyoff@chromium.org)\n' +
'* Parts Copyright (C) Copyright (C) 1998-2000 Greg J. Badros\n' +
'*\n' +
'* Use of this source code is governed by the LGPL, which can be found in the\n' +
'* COPYING.LGPL file.\n' +
'*/\n';
var kiwiBanner = '' +
'/*-----------------------------------------------------------------------------\n' +
'| Kiwi (TypeScript version)\n' +
'|\n' +
'| Copyright (c) 2014, Nucleic Development Team.\n' +
'|\n' +
'| Distributed under the terms of the Modified BSD License.\n' +
'|\n' +
'| The full license is in the file COPYING.txt, distributed with this software.\n' +
'|----------------------------------------------------------------------------*/\n';

function dist(kiwi, minify) {
    var input = CombinedStream.create();
    input.append(!kiwi ? 'var c = require(\'cassowary/bin/c\')\n' : 'var kiwi = require(\'kiwi/ts/bin/kiwi\')\n');
    input.append(fs.createReadStream('./tmp/autolayout.es6'));
    var output = fs.createWriteStream('dist/autolayout' + (kiwi ? '.kiwi' : '') + (minify ? '.min' : '') + '.js');
    output.write(banner);
    output.write(kiwi ? kiwiBanner : cassowaryBanner);
    var b = browserify(input, {
        debug: minify,
        standalone: 'AutoLayout',
        banner: banner
    });
    b.transform(babelify.configure({
        compact: false,
        ignore: /\/kiwi\//
    }));
    b.transform(envify({
        CASSOWARYJS: !kiwi
    }));
    if (minify) {
        b.plugin('minifyify', {
            map: 'autolayout.min.map',
            output: 'dist/autolayout.min.map',
            compressPath: function(p) {
                if (p.indexOf('kiwi') >= 0) {
                    return path.relative('node_modules/kiwi/ts/bin', p);
                }
                else {
                    return path.relative('tmp', p);
                }
            }
        });
    }
    b.bundle().on('error', function(err) {
        console.log('Error : ' + err.message);
    }).pipe(output);
}
dist(false, false);
if (!argv.fast) {
    dist(false, true);
    dist(true, false);
}
//dist(true, true);
<|endoftext|>


<commit_before>//= require store/spree_frontend
//= require store/jquery.magnific-popup
//= require store/product_or

$(document).ready(function() {
  $('.zoom-img').magnificPopup({
    type:'image',
    zoom: {
      enabled: true
    }
  });
});
<commit_msg>Update spree_magnific.js<commit_after>//= require spree/frontend/spree_frontend
//= require spree/frontend/jquery.magnific-popup
//= require spree/frontend/product_or

$(document).ready(function() {
  $('.zoom-img').magnificPopup({
    type:'image',
    zoom: {
      enabled: true
    }
  });
});
<|endoftext|>


<commit_before>var assert = require('assert')
var separator = '~', escape = '!'
var SE = require('separator-escape')(separator, escape)

var isArray = Array.isArray
function isFunction (f) {
  return 'function' === typeof f
}
function isString (s) {
  return 'string' === typeof s
}
function head (opts) {
  return isArray(opts) ? opts[0] : opts
}
function tail (opts) {
  return isArray(opts) ? opts.slice(1) : []
}

function compose (stream, transforms, cb) {
  if(!stream) throw new Error('multiserver.compose: *must* pass stream')
  ;(function next (err, stream, i, addr) {
    if(err) {
      err.address = addr + '~' + err.address
      return cb(err)
    }
    else if(i >= transforms.length) {
      stream.address = addr
      return cb(null, stream)
    }
    else
      transforms[i](stream, function (err, _stream) {
        if(!err && !stream) throw new Error('expected error or stream')
        if(_stream) _stream.meta = _stream.meta || stream.meta
        next(err, _stream, i+1, err ? addr : (addr+'~'+_stream.address))
      })
  })(null, stream, 0, stream.address)
}

function asyncify(f) {
  return function(cb) {
    if (f.length) return f(cb)
    if (cb) {
      var result
      try{
        result = f()
      } catch(err) {return cb(err)}
      return cb(null, result)
    }
    return f()
  }
}

module.exports = function (ary, wrap) {
  if(!wrap) wrap = function (e) { return e }
  var proto = head(ary)
  var trans = tail(ary)

  function parse (str) {
    var parts = SE.parse(str)
    var out = []
    for(var i = 0; i < parts.length; i++) {
      var v = ary[i].parse(parts[i])
      if(!v) return null
      out[i] = v
    }
    return out
  }

  function parseMaybe (str) {
    return  isString(str) ? parse(str) : str
  }

  return {
    name: ary.map(function (e) { return e.name }).join(separator),
    scope: proto.scope,
    client: function (_opts, cb) {
      var opts = parseMaybe(_opts)
      if(!opts) return cb(new Error('could not parse address:'+_opts))
      return proto.client(head(opts), function (err, stream) {
        if(err) return cb(err)
        compose(
          wrap(stream),
          trans.map(function (tr, i) { return tr.create(opts[i+1]) }),
          cb
        )
      })
    },
    // There should be a callback , called with
    // null when the server startsed to listen
    // (net.server.listen is async for example)
    server: function (onConnection, onError) {
      onError = onError || function (err) {
        console.error('server error, from', err.address)
        console.error(err.stack)
      }
      return asyncify(proto.server(function (stream) {
        compose(
          wrap(stream),
          trans.map(function (tr) { return tr.create() }),
          function (err, stream) {
            if(err) onError(err)
            else onConnection(stream)
          }
        )
      }))
    },
    parse: parse,
    stringify: function (scope) {
      var none
      var _ary = ary.map(function (e) {
        var v = e.stringify(scope)
        if(!v) none = true
        else return v
      })
      if(none) return
      return SE.stringify(_ary)
    }
  }
}

<commit_msg>Fix typo<commit_after>var assert = require('assert')
var separator = '~', escape = '!'
var SE = require('separator-escape')(separator, escape)

var isArray = Array.isArray
function isFunction (f) {
  return 'function' === typeof f
}
function isString (s) {
  return 'string' === typeof s
}
function head (opts) {
  return isArray(opts) ? opts[0] : opts
}
function tail (opts) {
  return isArray(opts) ? opts.slice(1) : []
}

function compose (stream, transforms, cb) {
  if(!stream) throw new Error('multiserver.compose: *must* pass stream')
  ;(function next (err, stream, i, addr) {
    if(err) {
      err.address = addr + '~' + err.address
      return cb(err)
    }
    else if(i >= transforms.length) {
      stream.address = addr
      return cb(null, stream)
    }
    else
      transforms[i](stream, function (err, _stream) {
        if(!err && !stream) throw new Error('expected error or stream')
        if(_stream) _stream.meta = _stream.meta || stream.meta
        next(err, _stream, i+1, err ? addr : (addr+'~'+_stream.address))
      })
  })(null, stream, 0, stream.address)
}

function asyncify(f) {
  return function(cb) {
    if (f.length) return f(cb)
    if (cb) {
      var result
      try{
        result = f()
      } catch(err) {return cb(err)}
      return cb(null, result)
    }
    return f()
  }
}

module.exports = function (ary, wrap) {
  if(!wrap) wrap = function (e) { return e }
  var proto = head(ary)
  var trans = tail(ary)

  function parse (str) {
    var parts = SE.parse(str)
    var out = []
    for(var i = 0; i < parts.length; i++) {
      var v = ary[i].parse(parts[i])
      if(!v) return null
      out[i] = v
    }
    return out
  }

  function parseMaybe (str) {
    return  isString(str) ? parse(str) : str
  }

  return {
    name: ary.map(function (e) { return e.name }).join(separator),
    scope: proto.scope,
    client: function (_opts, cb) {
      var opts = parseMaybe(_opts)
      if(!opts) return cb(new Error('could not parse address:'+_opts))
      return proto.client(head(opts), function (err, stream) {
        if(err) return cb(err)
        compose(
          wrap(stream),
          trans.map(function (tr, i) { return tr.create(opts[i+1]) }),
          cb
        )
      })
    },
    // There should be a callback , called with
    // null when the server started to listen.
    // (net.server.listen is async for example)
    server: function (onConnection, onError) {
      onError = onError || function (err) {
        console.error('server error, from', err.address)
        console.error(err.stack)
      }
      return asyncify(proto.server(function (stream) {
        compose(
          wrap(stream),
          trans.map(function (tr) { return tr.create() }),
          function (err, stream) {
            if(err) onError(err)
            else onConnection(stream)
          }
        )
      }))
    },
    parse: parse,
    stringify: function (scope) {
      var none
      var _ary = ary.map(function (e) {
        var v = e.stringify(scope)
        if(!v) none = true
        else return v
      })
      if(none) return
      return SE.stringify(_ary)
    }
  }
}

<|endoftext|>


<commit_before>Morph.addMethods({
  // zooming around

  startZoomingOuttaHere: function() {
    this.startZoomingTo(pt(this.world().getExtent().x + 300, -300), true, false, function() {this.remove();}.bind(this));
  },

  startZoomingTo: function(loc, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone) {
    this.startAnimating(animation.newMovement(this, loc, shouldAnticipateAtStart, shouldWiggleAtEnd), functionToCallWhenDone);
  },

  startAnimating: function(animator, functionToCallWhenDone) {
    this.stopAnimationProcess();

    functionToCallWhenDone = functionToCallWhenDone || function() {};
    animator.whenDoneCall(function() {this.stopAnimationProcess(); functionToCallWhenDone();}.bind(this))

    this._animationProcess = new PeriodicalExecuter(function(pe) {
      animator.doOneStep(pe);
    }, animator.timePerStep() / 1000);
  },

  stopAnimationProcess: function() {
    if (this._animationProcess) {
      this._animationProcess.stop();
      delete this._animationProcess;
    }
  },

  // wiggling

  wiggle: function() {
    this.startAnimating(animation.newWiggler(this));
  },

  // adding and removing to/from the world

  ensureIsInWorld: function(w, desiredLoc, shouldMoveToDesiredLocEvenIfAlreadyInWorld, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone) {
    this.stopAnimationProcess();
    var owner = this.owner;
    if (owner !== w) {
      var initialLoc = (!owner || this.world() !== w) ? pt(-50,-20) : owner.worldPoint(this.getPosition());
      w.addMorphAt(this, initialLoc);
      if (desiredLoc) {
        this.startZoomingTo(desiredLoc, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone);
      }
    } else {
      if (desiredLoc && shouldMoveToDesiredLocEvenIfAlreadyInWorld) {
        this.startZoomingTo(desiredLoc, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone);
      }
    }
  },

  ensureIsNotInWorld: function() {
    if (this.world()) {this.startZoomingOuttaHere();}
  },

  createDismissButton: function() {
    var b = new WindowControlMorph(new Rectangle(0, 0, 22, 22), 3, Color.primary.orange);
    b.relayToModel(this, {Trigger: "=ensureIsNotInWorld"});
    return b;
  },

  // scaling

  smoothlyScaleBackToNormalSize: function() {
    if (Math.abs(1.0 - this.getScale()) > 0.01) {
      var scaler = new Scaler(this, this.getExtent(), 10, function() {this.setScale(1.0);}.bind(this));
      new PeriodicalExecuter(function(pe) {
        try {
          scaler.doOneStep(pe);
        } catch (e) {
          logError(e, "smoothlyScaleBackToNormalSize()");
        }
      }, 0.1);
    }
  }
});

Object.subclass("Scaler", {
  initialize: function(morph, targetSize, numberOfSteps, functionToCallWhenDone) {
    this.morph = morph;
    this.targetSize = targetSize;
    this.numberOfSteps = numberOfSteps;
    this.done = functionToCallWhenDone;
    this.scalingFactor = this.calculateScalingFactor();
    return this;
  },

  calculateScalingFactor: function() {
    var originalBounds = this.morph.bounds();
    var targetRatio = Math.min(this.targetSize.x / originalBounds.width, this.targetSize.y / originalBounds.height);
    var ratioForEachStep = Math.pow(targetRatio, 1.0 / this.numberOfSteps);
    return ratioForEachStep;
  },

  doOneStep: function(pe) {
    if (this.numberOfSteps <= 0) {
      pe.stop();
      this.done();
      return;
    }
    this.numberOfSteps -= 1;
    this.morph.scaleBy(this.scalingFactor);
  },
});

<commit_msg>Made all LK "dismiss" buttons do the cool zooming-around thing.<commit_after>Morph.addMethods({
  // zooming around

  startZoomingOuttaHere: function() {
    this.startZoomingTo(pt(this.world().getExtent().x + 300, -300), true, false, function() {this.remove();}.bind(this));
  },

  startZoomingTo: function(loc, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone) {
    this.startAnimating(animation.newMovement(this, loc, shouldAnticipateAtStart, shouldWiggleAtEnd), functionToCallWhenDone);
  },

  startAnimating: function(animator, functionToCallWhenDone) {
    this.stopAnimationProcess();

    functionToCallWhenDone = functionToCallWhenDone || function() {};
    animator.whenDoneCall(function() {this.stopAnimationProcess(); functionToCallWhenDone();}.bind(this))

    this._animationProcess = new PeriodicalExecuter(function(pe) {
      animator.doOneStep(pe);
    }, animator.timePerStep() / 1000);
  },

  stopAnimationProcess: function() {
    if (this._animationProcess) {
      this._animationProcess.stop();
      delete this._animationProcess;
    }
  },

  // wiggling

  wiggle: function() {
    this.startAnimating(animation.newWiggler(this));
  },

  // adding and removing to/from the world

  ensureIsInWorld: function(w, desiredLoc, shouldMoveToDesiredLocEvenIfAlreadyInWorld, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone) {
    this.stopAnimationProcess();
    var owner = this.owner;
    if (owner !== w) {
      var initialLoc = (!owner || this.world() !== w) ? pt(-50,-20) : owner.worldPoint(this.getPosition());
      w.addMorphAt(this, initialLoc);
      if (desiredLoc) {
        this.startZoomingTo(desiredLoc, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone);
      }
    } else {
      if (desiredLoc && shouldMoveToDesiredLocEvenIfAlreadyInWorld) {
        this.startZoomingTo(desiredLoc, shouldAnticipateAtStart, shouldWiggleAtEnd, functionToCallWhenDone);
      }
    }
  },

  ensureIsNotInWorld: function() {
    if (this.world()) {this.startZoomingOuttaHere();}
  },

  createDismissButton: function() {
    var b = new WindowControlMorph(new Rectangle(0, 0, 22, 22), 3, Color.primary.orange);
    b.relayToModel(this, {Trigger: "=ensureIsNotInWorld"});
    return b;
  },

  // scaling

  smoothlyScaleBackToNormalSize: function() {
    if (Math.abs(1.0 - this.getScale()) > 0.01) {
      var scaler = new Scaler(this, this.getExtent(), 10, function() {this.setScale(1.0);}.bind(this));
      new PeriodicalExecuter(function(pe) {
        try {
          scaler.doOneStep(pe);
        } catch (e) {
          logError(e, "smoothlyScaleBackToNormalSize()");
        }
      }, 0.1);
    }
  }
});

WindowMorph.addMethods({
    initiateShutdown: function() {
        if (this.isShutdown()) return;
        this.targetMorph.shutdown(); // shutdown may be prevented ...
        this.ensureIsNotInWorld(); // Changed by Adam from this.remove(), so that it does the cool zooming-around thing
        this.state = 'shutdown'; // no one will ever know...
        return true;
    },
});

Object.subclass("Scaler", {
  initialize: function(morph, targetSize, numberOfSteps, functionToCallWhenDone) {
    this.morph = morph;
    this.targetSize = targetSize;
    this.numberOfSteps = numberOfSteps;
    this.done = functionToCallWhenDone;
    this.scalingFactor = this.calculateScalingFactor();
    return this;
  },

  calculateScalingFactor: function() {
    var originalBounds = this.morph.bounds();
    var targetRatio = Math.min(this.targetSize.x / originalBounds.width, this.targetSize.y / originalBounds.height);
    var ratioForEachStep = Math.pow(targetRatio, 1.0 / this.numberOfSteps);
    return ratioForEachStep;
  },

  doOneStep: function(pe) {
    if (this.numberOfSteps <= 0) {
      pe.stop();
      this.done();
      return;
    }
    this.numberOfSteps -= 1;
    this.morph.scaleBy(this.scalingFactor);
  },
});

<|endoftext|>


<commit_before>'use strict';
var React = require('react');
var _ = require('underscore');
var moment = require('moment');
var globals = require('./globals');
var fetched = require('./fetched');
var form = require('../libs/bootstrap/form');
var modal = require('../libs/bootstrap/modal');
var panel = require('../libs/bootstrap/panel');
var parseAndLogError = require('./mixins').parseAndLogError;
var RestMixin = require('./rest').RestMixin;
var variantHgvsRender = require('./curator').variantHgvsRender;
var CuratorHistory = require('./curator_history');
var add_external_resource = require('./add_external_resource');
var external_url_map = globals.external_url_map;
var AddResourceId = add_external_resource.AddResourceId;

var Form = form.Form;
var FormMixin = form.FormMixin;
var Input = form.Input;
var Alert = modal.Alert;
var ModalMixin = modal.ModalMixin;
var Panel = panel.Panel;

var SelectVariant = React.createClass({
    mixins: [FormMixin, RestMixin, ModalMixin, CuratorHistory],

    contextTypes: {
        fetch: React.PropTypes.func,
        navigate: React.PropTypes.func
    },

    getInitialState: function() {
        return {
            variantIdType: 'select',
            variantLoaded: false,
            variantData: null
        };
    },

    // Update the variantData upon interaction with the Add Resource modal
    updateVariantData: function(data) {
        this.setState({submitResourceBusy: false});
        this.context.navigate('/variant-central/?variant=' + data.uuid);
    },

    // Handle change of the select Variant Type dropdown
    handleChange: function(ref, e) {
        if (ref === 'variantIdType' && this.refs[ref].getValue()) {
            this.setState({variantIdType: this.refs[ref].getValue()});
        }
    },

    render: function() {
        return (

{this.props.context.title}

                    <Panel panelClassName="panel-select-variant">
                        <Form formClassName="form-horizontal form-std">
                            {!this.state.variantLoaded ?

                                    <Input type="select" ref="variantIdType" label="Select Variant by ID type"
                                        labelClassName="col-sm-5 col-md-4 control-label" value={this.state.variantIdType} wrapperClassName="col-sm-7 col-md-8" groupClassName="form-group"
                                        defaultValue="select" handleChange={this.handleChange} inputDisabled={this.state.variantLoaded}>
                                        <option value="select" disabled>Select</option>
                                        <option value="none" disabled></option>
                                        <option value="ClinVar Variation ID">ClinVar Variation ID</option>
                                        <option value="ClinGen Allele Registry ID (CA ID)">ClinGen Allele Registry ID (CA ID)</option>
                                    </Input>

Note: Select ID type based on the instructions below. Use the ClinVar VariationID whenever possible.

                                    {this.state.variantIdType == "ClinVar Variation ID" ?

                                        <AddResourceId resourceType="clinvar" wrapperClass="modal-buttons-wrapper" protocol={this.props.href_url.protocol}
                                            buttonText={this.state.variantData ? "Edit ClinVar ID" : "Add ClinVar ID" } initialFormValue={this.state.variantData && this.state.variantData.clinvarVariantId}
                                            modalButtonText="Save and View Evidence" updateParentForm={this.updateVariantData} buttonOnly={true} />

                                    : null}
                                    {this.state.variantIdType == "ClinGen Allele Registry ID (CA ID)" ?

                                        <AddResourceId resourceType="car" wrapperClass="modal-buttons-wrapper" protocol={this.props.href_url.protocol}
                                            buttonText={this.state.variantData ? "Edit CA ID" : "Add CA ID" } initialFormValue={this.state.variantData && this.state.variantData.carVariantId}
                                            modalButtonText="Save and View Evidence" updateParentForm={this.updateVariantData} buttonOnly={true} />

                                    : null}

                                        Note: This version of the interface currently returns evidence for SNVs (single nucleotide variants) only. We are currently working to optimize the evidence returned for non-SNVs. However, the interface supports the evaluation/interpretation of any variant.

                                        Instructions (please follow this order to determine correct ID for variant)

Search ClinVar for variant.

If found in ClinVar, select “ClinVar VariationID” from the pull-down to enter it.

If not found in ClinVar, search the ClinGen Allele Registry with a valid HGVS term for that variant.

If ClinGen Allele Registry returns a ClinVar ID, select “ClinVar VariationID” from the pull-down to enter it.

If ClinGen Allele Registry does not find a ClinVar ID, register the variant to return a CA ID and then select "ClinGen Allele Registry ID (CA ID)" from the pull-down and enter the CA ID.

                            : null}
                        </Form>
                    </Panel>

        );
    }
});

globals.curator_page.register(SelectVariant, 'curator_page', 'select-variant');
<commit_msg>Added 'target' attribute to external links in the variation selection interface<commit_after>'use strict';
var React = require('react');
var _ = require('underscore');
var moment = require('moment');
var globals = require('./globals');
var fetched = require('./fetched');
var form = require('../libs/bootstrap/form');
var modal = require('../libs/bootstrap/modal');
var panel = require('../libs/bootstrap/panel');
var parseAndLogError = require('./mixins').parseAndLogError;
var RestMixin = require('./rest').RestMixin;
var variantHgvsRender = require('./curator').variantHgvsRender;
var CuratorHistory = require('./curator_history');
var add_external_resource = require('./add_external_resource');
var external_url_map = globals.external_url_map;
var AddResourceId = add_external_resource.AddResourceId;

var Form = form.Form;
var FormMixin = form.FormMixin;
var Input = form.Input;
var Alert = modal.Alert;
var ModalMixin = modal.ModalMixin;
var Panel = panel.Panel;

var SelectVariant = React.createClass({
    mixins: [FormMixin, RestMixin, ModalMixin, CuratorHistory],

    contextTypes: {
        fetch: React.PropTypes.func,
        navigate: React.PropTypes.func
    },

    getInitialState: function() {
        return {
            variantIdType: 'select',
            variantLoaded: false,
            variantData: null
        };
    },

    // Update the variantData upon interaction with the Add Resource modal
    updateVariantData: function(data) {
        this.setState({submitResourceBusy: false});
        this.context.navigate('/variant-central/?variant=' + data.uuid);
    },

    // Handle change of the select Variant Type dropdown
    handleChange: function(ref, e) {
        if (ref === 'variantIdType' && this.refs[ref].getValue()) {
            this.setState({variantIdType: this.refs[ref].getValue()});
        }
    },

    render: function() {
        return (

{this.props.context.title}

                    <Panel panelClassName="panel-select-variant">
                        <Form formClassName="form-horizontal form-std">
                            {!this.state.variantLoaded ?

                                    <Input type="select" ref="variantIdType" label="Select Variant by ID type"
                                        labelClassName="col-sm-5 col-md-4 control-label" value={this.state.variantIdType} wrapperClassName="col-sm-7 col-md-8" groupClassName="form-group"
                                        defaultValue="select" handleChange={this.handleChange} inputDisabled={this.state.variantLoaded}>
                                        <option value="select" disabled>Select</option>
                                        <option value="none" disabled></option>
                                        <option value="ClinVar Variation ID">ClinVar Variation ID</option>
                                        <option value="ClinGen Allele Registry ID (CA ID)">ClinGen Allele Registry ID (CA ID)</option>
                                    </Input>

Note: Select ID type based on the instructions below. Use the ClinVar VariationID whenever possible.

                                    {this.state.variantIdType == "ClinVar Variation ID" ?

                                        <AddResourceId resourceType="clinvar" wrapperClass="modal-buttons-wrapper" protocol={this.props.href_url.protocol}
                                            buttonText={this.state.variantData ? "Edit ClinVar ID" : "Add ClinVar ID" } initialFormValue={this.state.variantData && this.state.variantData.clinvarVariantId}
                                            modalButtonText="Save and View Evidence" updateParentForm={this.updateVariantData} buttonOnly={true} />

                                    : null}
                                    {this.state.variantIdType == "ClinGen Allele Registry ID (CA ID)" ?

                                        <AddResourceId resourceType="car" wrapperClass="modal-buttons-wrapper" protocol={this.props.href_url.protocol}
                                            buttonText={this.state.variantData ? "Edit CA ID" : "Add CA ID" } initialFormValue={this.state.variantData && this.state.variantData.carVariantId}
                                            modalButtonText="Save and View Evidence" updateParentForm={this.updateVariantData} buttonOnly={true} />

                                    : null}

                                        Note: This version of the interface currently returns evidence for SNVs (single nucleotide variants) only. We are currently working to optimize the evidence returned for non-SNVs. However, the interface supports the evaluation/interpretation of any variant.

                                        Instructions (please follow this order to determine correct ID for variant)

Search ClinVar for variant.

If found in ClinVar, select “ClinVar VariationID” from the pull-down to enter it.

If not found in ClinVar, search the ClinGen Allele Registry with a valid HGVS term for that variant.

If ClinGen Allele Registry returns a ClinVar ID, select “ClinVar VariationID” from the pull-down to enter it.

If ClinGen Allele Registry does not find a ClinVar ID, register the variant to return a CA ID and then select "ClinGen Allele Registry ID (CA ID)" from the pull-down and enter the CA ID.

                            : null}
                        </Form>
                    </Panel>

        );
    }
});

globals.curator_page.register(SelectVariant, 'curator_page', 'select-variant');
<|endoftext|>


<commit_before>import SsrAuthChainPreset, {xorshift128plus} from './ssr-auth-chain';

/**
 * Calculates the index of the Array where item X should be placed, assuming the Array is sorted.
 * @param {Array} array The array containing the items.
 * @param {number} x The item that needs to be added to the array.
 * @param {number} low Initial Index that is used to start searching, optional.
 * @param {number} high The maximum Index that is used to stop searching, optional.
 * @return {number} the index where item X should be placed.
 */
function bisect_left(array, x, low = 0, high = array.length) {
  let mid;
  while (low < high) {
    mid = (low + high) >> 1;
    if (array[mid] < x) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return low;
}

/**
 * @description
 *   shadowsocksr "auth_chain_b" implementation.
 *
 * @notice
 *   This preset should be used together with "ss-base" and "ss-stream-cipher".
 *
 * @examples
 *   [
 *     {"name": "ss-base"},
 *     {"name": "ssr-auth-chain-b"},
 *     {"name": "ss-stream-cipher","params": {"method": "aes-128-ctr"}}
 *   ]
 */
export default class SsrAuthChainBPreset extends SsrAuthChainPreset {

  _data_size_list = [];

  _data_size_list2 = [];

  constructor(params) {
    super(params);
    this._salt = 'auth_chain_b';
    const rng = xorshift128plus();
    rng.init_from_bin(SsrAuthChainPreset.userKey);
    // _data_size_list
    let len = rng.next().mod(8).add(4).toNumber();
    for (let i = 0; i < len; ++i) {
      this._data_size_list.push(rng.next().mod(2340).mod(2040).mod(1440).toNumber());
    }
    // _data_size_list2
    len = rng.next().mod(16).add(8).toNumber();
    for (let i = 0; i < len; ++i) {
      this._data_size_list2.push(rng.next().mod(2340).mod(2040).mod(1440).toNumber());
    }
    this._data_size_list.sort((a, b) => a - b);
    this._data_size_list2.sort((a, b) => a - b);
  }

  onDestroy() {
    super.onDestroy();
    this._data_size_list = null;
    this._data_size_list2 = null;
  }

  getRandomBytesLengthForTcp(seed, base, rng) {
    if (base >= 1440) {
      return 0;
    }
    rng.init_from_bin_datalen(seed, base);

    const list_1 = this._data_size_list;
    const list_2 = this._data_size_list2;
    const overhead = this._overhead;

    let pos = bisect_left(list_1, base + overhead);
    pos = pos + rng.next().mod(list_1.length).toNumber();
    if (pos < list_1.length) {
      return list_1[pos] - base - overhead;
    }

    pos = bisect_left(list_2, base + overhead);
    pos = pos + rng.next().mod(list_2.length).toNumber();
    if (pos < list_2.length) {
      return list_2[pos] - base - overhead;
    }

    if (pos < pos + list_2.length - 1) {
      return 0;
    }

    let random_bytes_len;
    if (base > 1300) {
      random_bytes_len = rng.next().mod(31);
    } else if (base > 900) {
      random_bytes_len = rng.next().mod(127);
    } else if (base > 400) {
      random_bytes_len = rng.next().mod(521);
    } else {
      random_bytes_len = rng.next().mod(1021);
    }
    return random_bytes_len.toNumber();
  }

}
<commit_msg>presets: fixed a bug in random bytes length calculation<commit_after>import SsrAuthChainPreset, {xorshift128plus} from './ssr-auth-chain';

/**
 * Calculates the index of the Array where item X should be placed, assuming the Array is sorted.
 * @param {Array} array The array containing the items.
 * @param {number} x The item that needs to be added to the array.
 * @param {number} low Initial Index that is used to start searching, optional.
 * @param {number} high The maximum Index that is used to stop searching, optional.
 * @return {number} the index where item X should be placed.
 */
function bisect_left(array, x, low = 0, high = array.length) {
  let mid;
  while (low < high) {
    mid = (low + high) >> 1;
    if (array[mid] < x) {
      low = mid + 1;
    } else {
      high = mid;
    }
  }
  return low;
}

/**
 * @description
 *   shadowsocksr "auth_chain_b" implementation.
 *
 * @notice
 *   This preset should be used together with "ss-base" and "ss-stream-cipher".
 *
 * @examples
 *   [
 *     {"name": "ss-base"},
 *     {"name": "ssr-auth-chain-b"},
 *     {"name": "ss-stream-cipher","params": {"method": "aes-128-ctr"}}
 *   ]
 */
export default class SsrAuthChainBPreset extends SsrAuthChainPreset {

  _data_size_list = [];

  _data_size_list2 = [];

  constructor(params) {
    super(params);
    this._salt = 'auth_chain_b';
    const rng = xorshift128plus();
    rng.init_from_bin(SsrAuthChainPreset.userKey);
    // _data_size_list
    let len = rng.next().mod(8).add(4).toNumber();
    for (let i = 0; i < len; ++i) {
      this._data_size_list.push(rng.next().mod(2340).mod(2040).mod(1440).toNumber());
    }
    // _data_size_list2
    len = rng.next().mod(16).add(8).toNumber();
    for (let i = 0; i < len; ++i) {
      this._data_size_list2.push(rng.next().mod(2340).mod(2040).mod(1440).toNumber());
    }
    this._data_size_list.sort((a, b) => a - b);
    this._data_size_list2.sort((a, b) => a - b);
  }

  onDestroy() {
    super.onDestroy();
    this._data_size_list = null;
    this._data_size_list2 = null;
  }

  getRandomBytesLengthForTcp(seed, base, rng) {
    if (base >= 1440) {
      return 0;
    }
    rng.init_from_bin_datalen(seed, base);

    const list_1 = this._data_size_list;
    const list_2 = this._data_size_list2;
    const overhead = this._overhead;

    let pos = bisect_left(list_1, base + overhead);
    pos = pos + rng.next().mod(list_1.length).toNumber();
    if (pos < list_1.length) {
      return list_1[pos] - base - overhead;
    }

    pos = bisect_left(list_2, base + overhead);
    const final_pos = pos + rng.next().mod(list_2.length).toNumber();
    if (final_pos < list_2.length) {
      return list_2[final_pos] - base - overhead;
    }

    if (final_pos < pos + list_2.length - 1) {
      return 0;
    }

    let random_bytes_len;
    if (base > 1300) {
      random_bytes_len = rng.next().mod(31);
    } else if (base > 900) {
      random_bytes_len = rng.next().mod(127);
    } else if (base > 400) {
      random_bytes_len = rng.next().mod(521);
    } else {
      random_bytes_len = rng.next().mod(1021);
    }
    return random_bytes_len.toNumber();
  }

}
<|endoftext|>


<commit_before><commit_msg>Make logo goto magma startpage<commit_after><|endoftext|>


<commit_before>// Copyright 2016-2021, University of Colorado Boulder

/**
 * a type that is used to move an energy chunk along a pre-defined path
 *
 * @author John Blanco
 * @author Andrew Adare
 * @author Chris Klusendorf (PhET Interactive Simulations)
 */

import dotRandom from '../../../../dot/js/dotRandom.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import merge from '../../../../phet-core/js/merge.js';
import PhetioObject from '../../../../tandem/js/PhetioObject.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import ArrayIO from '../../../../tandem/js/types/ArrayIO.js';
import BooleanIO from '../../../../tandem/js/types/BooleanIO.js';
import IOType from '../../../../tandem/js/types/IOType.js';
import NumberIO from '../../../../tandem/js/types/NumberIO.js';
import ReferenceIO from '../../../../tandem/js/types/ReferenceIO.js';
import EFACConstants from '../../common/EFACConstants.js';
import EnergyChunk from '../../common/model/EnergyChunk.js';
import energyFormsAndChanges from '../../energyFormsAndChanges.js';

class EnergyChunkPathMover extends PhetioObject {

  /**
   * @param {EnergyChunk} energyChunk - energy chunk to be moved
   * @param {Vector2[]} path - points along energy chunk path
   * @param {number} speed - in meters per second
   * @param {Object} [options]
   */
  constructor( energyChunk, path, speed, options ) {

    options = merge( {

      // phet-io
      tandem: Tandem.REQUIRED,
      phetioType: EnergyChunkPathMover.EnergyChunkPathMoverIO,
      phetioDynamicElement: true
    }, options );

    // validate args
    assert && assert( energyChunk instanceof EnergyChunk, `energyChunk is not of correct type: ${energyChunk}` );
    assert && assert( path.length > 0, 'Path must have at least one point' );
    assert && assert( speed >= 0, `speed must be a non-negative scalar. Received: ${speed}` );

    super( options );

    assert && Tandem.VALIDATION && this.isPhetioInstrumented() && assert( energyChunk.isPhetioInstrumented() );

    // @public (read-only) {EnergyChunk}
    this.energyChunk = energyChunk;

    // @private
    this.path = path;
    this.speed = speed;
    this.pathFullyTraversed = false;
    this.nextPoint = path[ 0 ];
  }

  // @public (EnergyChunkPathMoverIO)
  toStateObject() {
    return {
      path: ArrayIO( Vector2.Vector2IO ).toStateObject( this.path ),
      speed: this.speed,
      pathFullyTraversed: this.pathFullyTraversed,
      nextPoint: this.nextPoint,
      energyChunkReference: ReferenceIO( EnergyChunk.EnergyChunkIO ).toStateObject( this.energyChunk )
    };
  }

  // @public (EnergyChunkPathMoverIO)
  static stateToArgsForConstructor( stateObject ) {
    const energyChunk = ReferenceIO( EnergyChunk.EnergyChunkIO ).fromStateObject( stateObject.energyChunkReference );
    const path = ArrayIO( Vector2.Vector2IO ).fromStateObject( stateObject.path );
    return [ energyChunk, path, stateObject.speed ];
  }

  // @public (EnergyChunkPathMoverIO)
  applyState( stateObject ) {
    this.pathFullyTraversed = stateObject.pathFullyTraversed;

    // Find the actual reference to the current nextPoint, not just a new instance of Vector2 with the same value, see https://github.com/phetsims/energy-forms-and-changes/issues/357
    for ( let i = 0; i < this.path.length; i++ ) {
      const pathElement = this.path[ i ];
      if ( stateObject.nextPoint.x === pathElement.x && stateObject.nextPoint.y === pathElement.y ) {
        this.nextPoint = pathElement;
      }
    }
  }

  /**
   * advance chunk position along the path
   * @param  {number} dt - time step in seconds
   * @public
   */
  moveAlongPath( dt ) {

    let distanceToTravel = dt * this.speed;

    while ( distanceToTravel > 0 && !this.pathFullyTraversed ) {

      const chunkPosition = this.energyChunk.positionProperty.get();

      assert && assert( chunkPosition instanceof Vector2, `Expected a Vector2, got this: ${chunkPosition}` );

      const distanceToNextPoint = chunkPosition.distance( this.nextPoint );

      if ( distanceToTravel < distanceToNextPoint ) {

        // the energy chunk will not reach the next destination point during this step, so just move that direction
        const phi = this.nextPoint.minus( this.energyChunk.positionProperty.get() ).angle;
        const velocity = new Vector2( distanceToTravel, 0 ).rotated( phi );
        this.energyChunk.positionProperty.set( this.energyChunk.positionProperty.get().plus( velocity ) );
        distanceToTravel = 0; // no remaining distance
      }
      else {

        // arrived at next destination point
        distanceToTravel -= this.energyChunk.positionProperty.get().distance( this.nextPoint );
        this.energyChunk.positionProperty.set( this.nextPoint );

        if ( this.nextPoint === this.path[ this.path.length - 1 ] ) {

          // the end of the path has been reached
          this.pathFullyTraversed = true;
        }
        else {
          const indexOfCurrentNextPoint = this.path.indexOf( this.nextPoint );
          assert && assert( indexOfCurrentNextPoint !== -1,
            'This is likely a bug where nextPoint is a different Vector2 reference than on in this.path' );
          assert && assert( indexOfCurrentNextPoint < this.path.length - 1, 'should not be the last point yet' );

          // set the next destination point
          this.nextPoint = this.path[ indexOfCurrentNextPoint + 1 ];
        }
      }
    }
  }

  /**
   * get the last point in the path that the energy chunk will follow
   * @returns {Vector2}
   * @public
   */
  getFinalDestination() {
    return this.path[ this.path.length - 1 ];
  }

  /**
   * Create an energy chunk path entirely from offsets
   * @param parentPosition {Vector2} the position of the parent element that is creating the path
   * @param offsets {Vector2[]} offsets from the element position
   * @returns {Vector[]}
   * @public
   */
  static createPathFromOffsets( parentPosition, offsets ) {
    const path = [];

    for ( let i = 0; i < offsets.length; i++ ) {
      path.push( parentPosition.plus( offsets[ i ] ) );
    }

    return path;
  }

  /**
   * Create an energy chunk path for radiated energy chunks
   * @param startingPosition {Vector2} the starting position of the energy chunk
   * @param startingAngle {number} the angle (away from vertical) of the first segment in the path
   * @returns {Vector[]}
   * @public
   */
  static createRadiatedPath( startingPosition, startingAngle ) {
    const path = [];
    const segmentLength = 0.06; // in meters. empirically determined to look nice and make it past the top of the beaker
    const verticalSegment = new Vector2( 0, segmentLength );

    // calculate the first segment based on the desired starting angle
    const startingSegment = new Vector2( 0, segmentLength ).rotated( startingAngle );
    let currentPosition = startingPosition.plus( startingSegment );
    path.push( currentPosition );

    // add segments at random angles until the path gets close to the max height
    while ( currentPosition.plus( verticalSegment ).y < EFACConstants.SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT ) {
      currentPosition = currentPosition.plus( verticalSegment.rotated( ( dotRandom.nextDouble() - 0.5 ) * Math.PI / 4 ) );
      path.push( currentPosition );
    }

    // go straight up to the max height cutoff point
    const finalSegment = new Vector2( 0, EFACConstants.SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT - currentPosition.y );
    currentPosition = currentPosition.plus( finalSegment );
    path.push( currentPosition );

    return path;
  }

  /**
   * Create a straight-line energy chunk path at a valid random angle
   * @param position {Vector2}
   * @param validAngles {Range} the range of possible angles to be randomly chosen
   * @returns {Vector[]}
   * @public
   */
  static createRandomStraightPath( position, validAngles ) {
    const validRandomAngle = dotRandom.nextDouble() * ( validAngles.max - validAngles.min ) + validAngles.min;
    return this.createStraightPath( position, validRandomAngle );
  }

  /** Create a straight-line energy chunk path
   * @param position {Vector2} the position that the path is created from
   * @param angle {number} the angle of the path
   * @returns {Vector[]}
   * @public
   */
  static createStraightPath( position, angle ) {
    const path = [];

    // calculate the travel segment based on how high the chunk should go
    const yDistance = EFACConstants.SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT - position.y;
    const xDistance = yDistance / Math.tan( angle ) + position.x;
    path.push( new Vector2( xDistance, yDistance ) );

    return path;
  }
}

EnergyChunkPathMover.EnergyChunkPathMoverIO = new IOType( 'EnergyChunkPathMoverIO', {
  valueType: EnergyChunkPathMover,
  toStateObject: energyChunkPathMover => energyChunkPathMover.toStateObject(),
  stateToArgsForConstructor: EnergyChunkPathMover.stateToArgsForConstructor,
  applyState: ( energyChunkPathMover, stateObject ) => energyChunkPathMover.applyState( stateObject ),
  stateSchema: {
    path: ArrayIO( Vector2.Vector2IO ),
    speed: NumberIO,
    pathFullyTraversed: BooleanIO,
    nextPoint: Vector2.Vector2IO,
    energyChunkReference: ReferenceIO( EnergyChunk.EnergyChunkIO )
  }
} );

energyFormsAndChanges.register( 'EnergyChunkPathMover', EnergyChunkPathMover );
export default EnergyChunkPathMover;<commit_msg>Use Vector2IO, see https://github.com/phetsims/energy-forms-and-changes/issues/416<commit_after>// Copyright 2016-2021, University of Colorado Boulder

/**
 * a type that is used to move an energy chunk along a pre-defined path
 *
 * @author John Blanco
 * @author Andrew Adare
 * @author Chris Klusendorf (PhET Interactive Simulations)
 */

import dotRandom from '../../../../dot/js/dotRandom.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import merge from '../../../../phet-core/js/merge.js';
import PhetioObject from '../../../../tandem/js/PhetioObject.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import ArrayIO from '../../../../tandem/js/types/ArrayIO.js';
import BooleanIO from '../../../../tandem/js/types/BooleanIO.js';
import IOType from '../../../../tandem/js/types/IOType.js';
import NumberIO from '../../../../tandem/js/types/NumberIO.js';
import ReferenceIO from '../../../../tandem/js/types/ReferenceIO.js';
import EFACConstants from '../../common/EFACConstants.js';
import EnergyChunk from '../../common/model/EnergyChunk.js';
import energyFormsAndChanges from '../../energyFormsAndChanges.js';

class EnergyChunkPathMover extends PhetioObject {

  /**
   * @param {EnergyChunk} energyChunk - energy chunk to be moved
   * @param {Vector2[]} path - points along energy chunk path
   * @param {number} speed - in meters per second
   * @param {Object} [options]
   */
  constructor( energyChunk, path, speed, options ) {

    options = merge( {

      // phet-io
      tandem: Tandem.REQUIRED,
      phetioType: EnergyChunkPathMover.EnergyChunkPathMoverIO,
      phetioDynamicElement: true
    }, options );

    // validate args
    assert && assert( energyChunk instanceof EnergyChunk, `energyChunk is not of correct type: ${energyChunk}` );
    assert && assert( path.length > 0, 'Path must have at least one point' );
    assert && assert( speed >= 0, `speed must be a non-negative scalar. Received: ${speed}` );

    super( options );

    assert && Tandem.VALIDATION && this.isPhetioInstrumented() && assert( energyChunk.isPhetioInstrumented() );

    // @public (read-only) {EnergyChunk}
    this.energyChunk = energyChunk;

    // @private
    this.path = path;
    this.speed = speed;
    this.pathFullyTraversed = false;
    this.nextPoint = path[ 0 ];
  }

  // @public (EnergyChunkPathMoverIO)
  toStateObject() {
    return {
      path: ArrayIO( Vector2.Vector2IO ).toStateObject( this.path ),
      speed: this.speed,
      pathFullyTraversed: this.pathFullyTraversed,
      nextPoint: Vector2.Vector2IO.toStateObject( this.nextPoint ),
      energyChunkReference: ReferenceIO( EnergyChunk.EnergyChunkIO ).toStateObject( this.energyChunk )
    };
  }

  // @public (EnergyChunkPathMoverIO)
  static stateToArgsForConstructor( stateObject ) {
    const energyChunk = ReferenceIO( EnergyChunk.EnergyChunkIO ).fromStateObject( stateObject.energyChunkReference );
    const path = ArrayIO( Vector2.Vector2IO ).fromStateObject( stateObject.path );
    return [ energyChunk, path, stateObject.speed ];
  }

  // @public (EnergyChunkPathMoverIO)
  applyState( stateObject ) {
    this.pathFullyTraversed = stateObject.pathFullyTraversed;

    // Find the actual reference to the current nextPoint, not just a new instance of Vector2 with the same value, see https://github.com/phetsims/energy-forms-and-changes/issues/357
    for ( let i = 0; i < this.path.length; i++ ) {
      const pathElement = this.path[ i ];
      if ( stateObject.nextPoint.x === pathElement.x && stateObject.nextPoint.y === pathElement.y ) {
        this.nextPoint = pathElement;
      }
    }
  }

  /**
   * advance chunk position along the path
   * @param  {number} dt - time step in seconds
   * @public
   */
  moveAlongPath( dt ) {

    let distanceToTravel = dt * this.speed;

    while ( distanceToTravel > 0 && !this.pathFullyTraversed ) {

      const chunkPosition = this.energyChunk.positionProperty.get();

      assert && assert( chunkPosition instanceof Vector2, `Expected a Vector2, got this: ${chunkPosition}` );

      const distanceToNextPoint = chunkPosition.distance( this.nextPoint );

      if ( distanceToTravel < distanceToNextPoint ) {

        // the energy chunk will not reach the next destination point during this step, so just move that direction
        const phi = this.nextPoint.minus( this.energyChunk.positionProperty.get() ).angle;
        const velocity = new Vector2( distanceToTravel, 0 ).rotated( phi );
        this.energyChunk.positionProperty.set( this.energyChunk.positionProperty.get().plus( velocity ) );
        distanceToTravel = 0; // no remaining distance
      }
      else {

        // arrived at next destination point
        distanceToTravel -= this.energyChunk.positionProperty.get().distance( this.nextPoint );
        this.energyChunk.positionProperty.set( this.nextPoint );

        if ( this.nextPoint === this.path[ this.path.length - 1 ] ) {

          // the end of the path has been reached
          this.pathFullyTraversed = true;
        }
        else {
          const indexOfCurrentNextPoint = this.path.indexOf( this.nextPoint );
          assert && assert( indexOfCurrentNextPoint !== -1,
            'This is likely a bug where nextPoint is a different Vector2 reference than on in this.path' );
          assert && assert( indexOfCurrentNextPoint < this.path.length - 1, 'should not be the last point yet' );

          // set the next destination point
          this.nextPoint = this.path[ indexOfCurrentNextPoint + 1 ];
        }
      }
    }
  }

  /**
   * get the last point in the path that the energy chunk will follow
   * @returns {Vector2}
   * @public
   */
  getFinalDestination() {
    return this.path[ this.path.length - 1 ];
  }

  /**
   * Create an energy chunk path entirely from offsets
   * @param parentPosition {Vector2} the position of the parent element that is creating the path
   * @param offsets {Vector2[]} offsets from the element position
   * @returns {Vector[]}
   * @public
   */
  static createPathFromOffsets( parentPosition, offsets ) {
    const path = [];

    for ( let i = 0; i < offsets.length; i++ ) {
      path.push( parentPosition.plus( offsets[ i ] ) );
    }

    return path;
  }

  /**
   * Create an energy chunk path for radiated energy chunks
   * @param startingPosition {Vector2} the starting position of the energy chunk
   * @param startingAngle {number} the angle (away from vertical) of the first segment in the path
   * @returns {Vector[]}
   * @public
   */
  static createRadiatedPath( startingPosition, startingAngle ) {
    const path = [];
    const segmentLength = 0.06; // in meters. empirically determined to look nice and make it past the top of the beaker
    const verticalSegment = new Vector2( 0, segmentLength );

    // calculate the first segment based on the desired starting angle
    const startingSegment = new Vector2( 0, segmentLength ).rotated( startingAngle );
    let currentPosition = startingPosition.plus( startingSegment );
    path.push( currentPosition );

    // add segments at random angles until the path gets close to the max height
    while ( currentPosition.plus( verticalSegment ).y < EFACConstants.SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT ) {
      currentPosition = currentPosition.plus( verticalSegment.rotated( ( dotRandom.nextDouble() - 0.5 ) * Math.PI / 4 ) );
      path.push( currentPosition );
    }

    // go straight up to the max height cutoff point
    const finalSegment = new Vector2( 0, EFACConstants.SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT - currentPosition.y );
    currentPosition = currentPosition.plus( finalSegment );
    path.push( currentPosition );

    return path;
  }

  /**
   * Create a straight-line energy chunk path at a valid random angle
   * @param position {Vector2}
   * @param validAngles {Range} the range of possible angles to be randomly chosen
   * @returns {Vector[]}
   * @public
   */
  static createRandomStraightPath( position, validAngles ) {
    const validRandomAngle = dotRandom.nextDouble() * ( validAngles.max - validAngles.min ) + validAngles.min;
    return this.createStraightPath( position, validRandomAngle );
  }

  /** Create a straight-line energy chunk path
   * @param position {Vector2} the position that the path is created from
   * @param angle {number} the angle of the path
   * @returns {Vector[]}
   * @public
   */
  static createStraightPath( position, angle ) {
    const path = [];

    // calculate the travel segment based on how high the chunk should go
    const yDistance = EFACConstants.SYSTEMS_SCREEN_ENERGY_CHUNK_MAX_TRAVEL_HEIGHT - position.y;
    const xDistance = yDistance / Math.tan( angle ) + position.x;
    path.push( new Vector2( xDistance, yDistance ) );

    return path;
  }
}

EnergyChunkPathMover.EnergyChunkPathMoverIO = new IOType( 'EnergyChunkPathMoverIO', {
  valueType: EnergyChunkPathMover,
  toStateObject: energyChunkPathMover => energyChunkPathMover.toStateObject(),
  stateToArgsForConstructor: EnergyChunkPathMover.stateToArgsForConstructor,
  applyState: ( energyChunkPathMover, stateObject ) => energyChunkPathMover.applyState( stateObject ),
  stateSchema: {
    path: ArrayIO( Vector2.Vector2IO ),
    speed: NumberIO,
    pathFullyTraversed: BooleanIO,
    nextPoint: Vector2.Vector2IO,
    energyChunkReference: ReferenceIO( EnergyChunk.EnergyChunkIO )
  }
} );

energyFormsAndChanges.register( 'EnergyChunkPathMover', EnergyChunkPathMover );
export default EnergyChunkPathMover;<|endoftext|>


<commit_before>/* Globals: configuration, notifications */

;(function () {
  'use strict'

  var config = {}

  var urlObserver = new window.MutationObserver(function(mutations, observer) {
    setTimeout(main)
  })

  urlObserver.observe(document.getElementById('js-pjax-loader-bar'), {
    attributes: true,
    attributeFilter: ['class']
  })

  function main() {
    for(var prop in config) {
      if (config[prop] && features[prop]) {
        features[prop]()
      }
    }
  }

  configuration.get(function (items) {
    config = items
    main()
  })

  insertStyles()

  // -----------------------------------------------------------------------------
  // Features

  var features = {
    showOutdatedComments: function() {
      var outdatedDiffs = document.getElementsByClassName('outdated-diff-comment-container')

      for(var i = 0; i < outdatedDiffs.length; i++) {
        outdatedDiffs[i].classList.add('open')
      }
    },

    highlightOutdatedDiffIcons: function() {
      var octicons = document.querySelectorAll('.discussion-timeline .discussion-item-icon .octicon-x')

      for(var i = 0; i < octicons.length; i++) {
        var discussionItemIcon = octicons[i].parentElement
        discussionItemIcon.style.backgroundColor = '#ffefc6'
        discussionItemIcon.style.color = '#4c4a42'
      }
    },

    showCurrentDiffFileName: function() {
      var prtoolbar = document.querySelector('.pr-toolbar.js-sticky')
      if (! prtoolbar) return

      var diffbar = prtoolbar.querySelector('.diffbar')
      var headers = document.getElementsByClassName('file-header')
      var blobs   = document.getElementsByClassName('blob-wrapper')

      var diffbarItem = document.getElementById('__ghcape-current-file')
      if (! diffbarItem) {
        diffbarItem = createDiffItem()
        diffbar.insertBefore(diffbarItem, diffbar.querySelector('.diffbar-item.diffstat').nextElementSibling)
      }

      document.addEventListener('scroll', onScroll, false)

      onScroll()

      function onScroll() {
        var index = firstIndexInViewport(blobs)
        var currentHeader = headers[index]

        diffbarItem.style.display = prtoolbar.style.position === 'fixed' ? 'block' : 'none'

        if (currentHeader) {
          diffbarItem.setAttribute('aria-label', currentHeader.dataset.path)
          diffbarItem.firstChild.innerHTML = currentHeader.dataset.path.split('/').slice(-1)
        }
      }

      function createDiffItem() {
        var diffbarItem = document.createElement('div')
        var path = document.createElement('div')

        diffbarItem.id = '__ghcape-current-file'
        diffbarItem.className = 'diffbar-item'
        diffbarItem.classList.add('tooltipped', 'tooltipped-s')

        path.style.maxWidth        = config.showHideAllButtons ? "170px" : "290px"
        path.style.marginRight  = "0"
        path.style.whiteSpace   = "nowrap"
        path.style.textOverflow = "ellipsis"
        path.style.overflow     = "hidden"

        diffbarItem.appendChild(path)

        return diffbarItem
      }
    },

    collapsableDiffs: function() {
      makeCollapsable({
        trigger: 'file-header',
        targets: ['file-header', 'file-info'],
        toggleableSibling: 'blob-wrapper'
      })
    },

    showHideAllButtons: function() {
      var actions = document.querySelector('.pr-toolbar.js-sticky .toc-select ~ .float-right') // Ugh

      if (actions && actions.getElementsByClassName('__ghcape-show-hide-all').length === 0) {
        var headers = Array.prototype.slice.call(document.getElementsByClassName('file-header'))

        var showAll = document.createElement('button')
        showAll.innerHTML = 'Show all'
        showAll.className = 'diffbar-item btn-link muted-link __ghcape-show-hide-all'
        showAll.onclick = function() { changeHadersVisibillity('remove') }

        var hideAll = document.createElement('button')
        hideAll.innerHTML = 'Hide all'
        hideAll.className = 'diffbar-item btn-link muted-link __ghcape-show-hide-all'
        hideAll.onclick = function() { changeHadersVisibillity('add') } // This will potentially break the filename on the sticky header

        actions.appendChild(showAll)
        actions.appendChild(hideAll)
      }

      function changeHadersVisibillity(method) {
        headers.forEach(function(header) {
          var code = nextByClass(header, 'blob-wrapper')
          if (code) code.classList[method]('__ghcape-hidden')
        })
      }
    },

    collapsableCommits: function() {
      makeCollapsable({
        trigger: 'commit-group-title',
        toggleableSibling: 'commit-group'
      })
    },

    toggleContributions: function() {
      var actionClasses = [
        { trigger: '.text-green', code: 'blob-code-addition' },
        { trigger: '.text-red', code: 'blob-code-deletion' }
      ]

      actionClasses.forEach(function(classes) {
        var trigger = document.querySelector('.diffbar-item.diffstat > ' + classes.trigger)
        if (! trigger) return

        var tooltipText = { 'Hide': 'Show', 'Show': 'Hide' }

        trigger.style.cursor = 'pointer'
        trigger.classList.add('tooltipped', 'tooltipped-s')
        trigger.setAttribute('aria-label', 'Hide')

        trigger.addEventListener('click', function() {
          var code = document.getElementsByClassName('blob-code ' + classes.code)
          var newTooltipText = tooltipText[trigger.getAttribute('aria-label')]
          trigger.setAttribute('aria-label', 'Loading')

          setTimeout(function () {
            for(var i = 0; i < code.length; i++) {
              code[i].parentNode.classList.toggle('__ghcape-hidden')
            }
            trigger.setAttribute('aria-label', newTooltipText)
          })
        }, true)
      })
    },

    resizeableSplittedDiffs: function() {
      var splitButton = document.querySelector('.BtnGroup [aria-label="Viewing diff in split mode"]')

      if(! splitButton) return

      var datas = Array.prototype.slice.call(document.querySelectorAll('.data:not(.__ghcape-draggable)'))
      var codeWidth = null
      var draggableBarWidth = null

      datas.forEach(function(data) {
        var table = data.firstElementChild

        if (! table) return

        var code = findFirstTd(table)

        if(! draggableBarWidth) {
          var tr = table.querySelector('tr:not(.js-expandable-line)')
          draggableBarWidth = (tr.clientWidth / 2) + 'px'
        }

        if(! codeWidth) {
          codeWidth = getComputedStyle(code, null).getPropertyValue('width')
          codeWidth = parseInt(codeWidth, 10) + 'px'
        }

        var draggableBar = document.createElement('div')
        draggableBar.className = '__ghcape-draggable-bar'
        draggableBar.style.top = 0
        draggableBar.style.left = draggableBarWidth

        code.style.width = codeWidth

        data.classList.add('__ghcape-draggable')
        data.appendChild(draggableBar)

        setTimeout(function() { attachEvents(draggableBar) }, 0)
      })

      function attachEvents(draggableBar) {
        var table    = draggableBar.previousElementSibling
        var maxWidth = 970
        var minWidth = 370
        var offset   = 0
        var mouseX   = 0
        var td       = null

        var move = function(event) {
          td = td || findFirstTd(table)

          var direction = mouseX === 0 ? 1 : (event.pageX - mouseX)
          var width = (parseInt(td.style.width, 10) + direction)

          if (width >= minWidth && width < maxWidth) {
            td.style.width = width + 'px'
            draggableBar.style.left = (event.clientX - offset) + 'px'
            mouseX = event.pageX
          }
        }

        draggableBar.addEventListener('mousedown', function(e) {
          offset = e.clientX - parseInt(draggableBar.style.left, 10)
          table.parentElement.style.userSelect = 'none'
          document.addEventListener('mousemove', move, false)
        }, false)

        document.addEventListener('mouseup', function() {
          table.parentElement.style.userSelect = 'inherit'
          document.removeEventListener('mousemove', move, false)
        }, false)
      }

      function findFirstTd(table) {
        return table.querySelector('.blob-num:not(.blob-num-expandable):not(.blob-num-hunk) ~ td')
      }
    },

    notifications: function() {
      notifications.load()
    }
  }

  // -----------------------------------------------------------------------------
  // Utils

  function makeCollapsable(classes) {
    var triggers = document.getElementsByClassName(classes.trigger)
    var targets  = classes.targets || [ classes.trigger ]

    for(var i = 0; i < triggers.length; i++) {
      triggers[i].addEventListener('click', togglePanel)
      triggers[i].style.cursor = 'pointer'
    }

    function togglePanel(event) {
      if (! containsAnyClass(event.target, targets)) return

      var code = nextByClass(this, classes.toggleableSibling)
      if (code) {
        code.classList.toggle('__ghcape-hidden')
      }
    }
  }

  function prevByClass(node, className) {
    return findSibling(node, 'previous', className)
  }

  function nextByClass(node, className) {
    return findSibling(node, 'next', className)
  }

  function findSibling(node, direction, className) {
    while (node = node[direction + 'Sibling']) {
      if (node.classList && node.classList.contains(className)) {
        return node
      }
    }
  }

  function containsAnyClass(el, classes) {
    for(var i = 0; i < classes.length; i++) {
      if (el.classList.contains(classes[i])) {
        return true
      }
    }
    return false
  }

  function firstIndexInViewport(els) {
    for(var i = 0; i < els.length; i++) {
      if (inViewport(els[i])) {
        return i
      }
    }
  }

  function inViewport(el) {
    var rect = el.getBoundingClientRect()
    var windowHeight = window.innerHeight || document.documentElement.clientHeight
    return rect.height && rect.top <= windowHeight && (rect.top + rect.height) >= 0
  }

  function insertStyles() {
    var style = document.createElement('style')
    var styles = [
      '.__ghcape-hidden { display: none !important; }',

      '.__ghcape-show-hide-all { line-height: 28px; }',

      '.__ghcape-draggable { position: relative; }',
      '.__ghcape-draggable .diff-table.file-diff-split { table-layout: auto; }',
      '.__ghcape-draggable td.blob-num { width: inherit; min-width: inherit; }',

      '.__ghcape-draggable-bar {',
        'height: 100%; width: 8px;',
        'top: 0; position: absolute;',
        'border-left: 2px solid #d8d8d8; border-right: 2px solid #d8d8d8;',
        'background: #F7F7F7;',
        'cursor: col-resize;',
      '}'
    ]
    style.innerHTML = styles.join(' ')

    document.body.appendChild(style)
  }
})()
<commit_msg>Fix styles for the show/hide all buttons + path names<commit_after>/* Globals: configuration, notifications */

;(function () {
  'use strict'

  var config = {}

  var urlObserver = new window.MutationObserver(function(mutations, observer) {
    setTimeout(main)
  })

  urlObserver.observe(document.getElementById('js-pjax-loader-bar'), {
    attributes: true,
    attributeFilter: ['class']
  })

  function main() {
    for(var prop in config) {
      if (config[prop] && features[prop]) {
        features[prop]()
      }
    }
  }

  configuration.get(function (items) {
    config = items
    main()
  })

  insertStyles()

  // -----------------------------------------------------------------------------
  // Features

  var features = {
    showOutdatedComments: function() {
      var outdatedDiffs = document.getElementsByClassName('outdated-diff-comment-container')

      for(var i = 0; i < outdatedDiffs.length; i++) {
        outdatedDiffs[i].classList.add('open')
      }
    },

    highlightOutdatedDiffIcons: function() {
      var octicons = document.querySelectorAll('.discussion-timeline .discussion-item-icon .octicon-x')

      for(var i = 0; i < octicons.length; i++) {
        var discussionItemIcon = octicons[i].parentElement
        discussionItemIcon.style.backgroundColor = '#ffefc6'
        discussionItemIcon.style.color = '#4c4a42'
      }
    },

    showCurrentDiffFileName: function() {
      var prtoolbar = document.querySelector('.pr-toolbar.js-sticky')
      if (! prtoolbar) return

      var diffbar = prtoolbar.querySelector('.diffbar')
      var headers = document.getElementsByClassName('file-header')
      var blobs   = document.getElementsByClassName('blob-wrapper')

      var diffbarItem = document.getElementById('__ghcape-current-file')
      if (! diffbarItem) {
        diffbarItem = createDiffItem()
        diffbar.insertBefore(diffbarItem, diffbar.querySelector('.diffbar-item.diffstat').nextElementSibling)
      }

      document.addEventListener('scroll', onScroll, false)

      onScroll()

      function onScroll() {
        var index = firstIndexInViewport(blobs)
        var currentHeader = headers[index]

        diffbarItem.style.display = prtoolbar.style.position === 'fixed' ? 'block' : 'none'

        if (currentHeader) {
          diffbarItem.setAttribute('aria-label', currentHeader.dataset.path)
          diffbarItem.firstChild.innerHTML = currentHeader.dataset.path.split('/').slice(-1)
        }
      }

      function createDiffItem() {
        var diffbarItem = document.createElement('div')
        var path = document.createElement('div')

        diffbarItem.id = '__ghcape-current-file'
        diffbarItem.className = 'diffbar-item'
        diffbarItem.classList.add('tooltipped', 'tooltipped-s')

        path.style.marginRight  = '0'
        path.style.whiteSpace   = 'nowrap'
        path.style.textOverflow = 'ellipsis'
        path.style.overflow     = 'hidden'

        if (! inSplitView() && viewingSubsetChanges()) {
          path.style.maxWidth = '65px'
        } else {
          path.style.maxWidth = config.showHideAllButtons ? '160px' : '290px'
        }

        diffbarItem.appendChild(path)

        return diffbarItem
      }
    },

    collapsableDiffs: function() {
      makeCollapsable({
        trigger: 'file-header',
        targets: ['file-header', 'file-info'],
        toggleableSibling: 'blob-wrapper'
      })
    },

    showHideAllButtons: function() {
      var actions = document.querySelector('.pr-toolbar.js-sticky .toc-select ~ .float-right') // Ugh

      if (actions && actions.getElementsByClassName('__ghcape-show-hide-all').length === 0) {
        var headers = Array.prototype.slice.call(document.getElementsByClassName('file-header'))
        var className = 'btn-link muted-link __ghcape-show-hide-all'

        if(! inSplitView() && viewingSubsetChanges()){
          className += ' __ghcape-hidden'
        }

        var showAll = document.createElement('button')
        showAll.innerHTML = 'Show all'
        showAll.className = className
        showAll.onclick = function() { changeHadersVisibillity('remove') }

        var hideAll = document.createElement('button')
        hideAll.innerHTML = 'Hide all'
        hideAll.className = className
        hideAll.onclick = function() { changeHadersVisibillity('add') } // This will potentially break the filename on the sticky header

        actions.appendChild(showAll)
        actions.appendChild(hideAll)
      }

      function changeHadersVisibillity(method) {
        headers.forEach(function(header) {
          var code = nextByClass(header, 'blob-wrapper')
          if (code) code.classList[method]('__ghcape-hidden')
        })
      }
    },

    collapsableCommits: function() {
      makeCollapsable({
        trigger: 'commit-group-title',
        toggleableSibling: 'commit-group'
      })
    },

    toggleContributions: function() {
      var actionClasses = [
        { trigger: '.text-green', code: 'blob-code-addition' },
        { trigger: '.text-red', code: 'blob-code-deletion' }
      ]

      actionClasses.forEach(function(classes) {
        var trigger = document.querySelector('.diffbar-item.diffstat > ' + classes.trigger)
        if (! trigger) return

        var tooltipText = { 'Hide': 'Show', 'Show': 'Hide' }

        trigger.style.cursor = 'pointer'
        trigger.classList.add('tooltipped', 'tooltipped-s')
        trigger.setAttribute('aria-label', 'Hide')

        trigger.addEventListener('click', function() {
          var code = document.getElementsByClassName('blob-code ' + classes.code)
          var newTooltipText = tooltipText[trigger.getAttribute('aria-label')]
          trigger.setAttribute('aria-label', 'Loading')

          setTimeout(function () {
            for(var i = 0; i < code.length; i++) {
              code[i].parentNode.classList.toggle('__ghcape-hidden')
            }
            trigger.setAttribute('aria-label', newTooltipText)
          })
        }, true)
      })
    },

    resizeableSplittedDiffs: function() {
      if(! inSplitView()) return

      var datas = Array.prototype.slice.call(document.querySelectorAll('.data:not(.__ghcape-draggable)'))
      var codeWidth = null
      var draggableBarWidth = null

      datas.forEach(function(data) {
        var table = data.firstElementChild

        if (! table) return

        var code = findFirstTd(table)

        if(! draggableBarWidth) {
          var tr = table.querySelector('tr:not(.js-expandable-line)')
          draggableBarWidth = (tr.clientWidth / 2) + 'px'
        }

        if(! codeWidth) {
          codeWidth = getComputedStyle(code, null).getPropertyValue('width')
          codeWidth = parseInt(codeWidth, 10) + 'px'
        }

        var draggableBar = document.createElement('div')
        draggableBar.className = '__ghcape-draggable-bar'
        draggableBar.style.top = 0
        draggableBar.style.left = draggableBarWidth

        code.style.width = codeWidth

        data.classList.add('__ghcape-draggable')
        data.appendChild(draggableBar)

        setTimeout(function() { attachEvents(draggableBar) }, 0)
      })

      function attachEvents(draggableBar) {
        var table    = draggableBar.previousElementSibling
        var maxWidth = 970
        var minWidth = 370
        var offset   = 0
        var mouseX   = 0
        var td       = null

        var move = function(event) {
          td = td || findFirstTd(table)

          var direction = mouseX === 0 ? 1 : (event.pageX - mouseX)
          var width = (parseInt(td.style.width, 10) + direction)

          if (width >= minWidth && width < maxWidth) {
            td.style.width = width + 'px'
            draggableBar.style.left = (event.clientX - offset) + 'px'
            mouseX = event.pageX
          }
        }

        draggableBar.addEventListener('mousedown', function(e) {
          offset = e.clientX - parseInt(draggableBar.style.left, 10)
          table.parentElement.style.userSelect = 'none'
          document.addEventListener('mousemove', move, false)
        }, false)

        document.addEventListener('mouseup', function() {
          table.parentElement.style.userSelect = 'inherit'
          document.removeEventListener('mousemove', move, false)
        }, false)
      }

      function findFirstTd(table) {
        return table.querySelector('.blob-num:not(.blob-num-expandable):not(.blob-num-hunk) ~ td')
      }
    },

    notifications: function() {
      notifications.load()
    }
  }

  // -----------------------------------------------------------------------------
  // Utils

  function makeCollapsable(classes) {
    var triggers = document.getElementsByClassName(classes.trigger)
    var targets  = classes.targets || [ classes.trigger ]

    for(var i = 0; i < triggers.length; i++) {
      triggers[i].addEventListener('click', togglePanel)
      triggers[i].style.cursor = 'pointer'
    }

    function togglePanel(event) {
      if (! containsAnyClass(event.target, targets)) return

      var code = nextByClass(this, classes.toggleableSibling)
      if (code) {
        code.classList.toggle('__ghcape-hidden')
      }
    }
  }

  function prevByClass(node, className) {
    return findSibling(node, 'previous', className)
  }

  function nextByClass(node, className) {
    return findSibling(node, 'next', className)
  }

  function findSibling(node, direction, className) {
    while (node = node[direction + 'Sibling']) {
      if (node.classList && node.classList.contains(className)) {
        return node
      }
    }
  }

  function containsAnyClass(el, classes) {
    for(var i = 0; i < classes.length; i++) {
      if (el.classList.contains(classes[i])) {
        return true
      }
    }
    return false
  }

  function firstIndexInViewport(els) {
    for(var i = 0; i < els.length; i++) {
      if (inViewport(els[i])) {
        return i
      }
    }
  }

  function inViewport(el) {
    var rect = el.getBoundingClientRect()
    var windowHeight = window.innerHeight || document.documentElement.clientHeight
    return rect.height && rect.top <= windowHeight && (rect.top + rect.height) >= 0
  }

  function inSplitView() {
    return !! document.querySelector('.BtnGroup [aria-label="Viewing diff in split mode"]')
  }

  function viewingSubsetChanges() {
    return document.getElementsByClassName('subset-files-tab').length
  }

  function insertStyles() {
    var style = document.createElement('style')
    var styles = [
      '.__ghcape-hidden { display: none !important; }',

      '.__ghcape-show-hide-all { margin-left: 8px; line-height: 28px; }',

      '.__ghcape-draggable { position: relative; }',
      '.__ghcape-draggable .diff-table.file-diff-split { table-layout: auto; }',
      '.__ghcape-draggable td.blob-num { width: inherit; min-width: inherit; }',

      '.__ghcape-draggable-bar {',
        'height: 100%; width: 8px;',
        'top: 0; position: absolute;',
        'border-left: 2px solid #d8d8d8; border-right: 2px solid #d8d8d8;',
        'background: #F7F7F7;',
        'cursor: col-resize;',
      '}'
    ]
    style.innerHTML = styles.join(' ')

    document.body.appendChild(style)
  }
})()
<|endoftext|>


<commit_before>import { Comments } from 'meteor/example-forum';

Comments.addDefaultView(terms => {
  const validFields = _.pick(terms, 'userId');
  return ({
    selector: {
      ...validFields,
    }
  });
})

Comments.addView("postCommentsDeleted", function (terms) {
  return {
    selector: {postId: terms.postId},
    options: {sort: {deleted:-1}}
  };
});

Comments.addView("postCommentsTop", function (terms) {
  return {
    selector: { postId: terms.postId, deleted: {$ne:true}},
    options: {sort: {baseScore: -1, postedAt: -1}}
  };
});

Comments.addView("postCommentsNew", function (terms) {
  return {
    selector: { postId: terms.postId, deleted: {$ne:true}},
    options: {sort: {postedAt: -1}}
  };
});

Comments.addView("postCommentsBest", function (terms) {
  return {
    selector: { postId: terms.postId, deleted: {$ne:true}},
    options: {sort: {baseScore: -1}, postedAt: -1}
  };
});

Comments.addView("allRecentComments", function (terms) {
  return {
    selector: { deleted:{$ne:true} },
    options: {sort: {postedAt: -1}, limit: terms.limit || 5},
  };
});

Comments.addView("recentComments", function (terms) {
  return {
    selector: { deleted:{$ne:true}, score:{$gt:0}},
    options: {sort: {postedAt: -1}, limit: terms.limit || 5},
  };
});
Comments.addView("topRecentComments", function (terms) {
  return {
    selector: { deleted:{$ne:true}, score:{$gt:0}, postId:terms.postId},
    options: {sort: {baseScore: -1}, limit: terms.limit || 3},
  };
});

Comments.addView("postCommentsUnread", function (terms) {
  return {
    selector: {
      postId: terms.postId,
      deleted: {$ne:true},
    },
    options: {sort: {postedAt: -1}, limit: terms.limit || 5},
  };
});
<commit_msg>Change to how we query comments (also query deletedPublic comments)<commit_after>import { Comments } from 'meteor/example-forum';

Comments.addDefaultView(terms => {
  const validFields = _.pick(terms, 'userId');
  return ({
    selector: {
      $or: [{$and: [{deleted: true}, {deletedPublic: true}]}, {deleted: {$ne: true}}],
      ...validFields,
    }
  });
})

Comments.addView("postCommentsDeleted", function (terms) {
  return {
    selector: {
      deleted: true,
      postId: terms.postId
    },
    options: {sort: {deleted:-1}}
  };
});

Comments.addView("postCommentsTop", function (terms) {
  return {
    selector: { postId: terms.postId },
    options: {sort: {baseScore: -1, postedAt: -1}}
  };
});

Comments.addView("postCommentsNew", function (terms) {
  return {
    selector: { postId: terms.postId },
    options: {sort: {postedAt: -1}}
  };
});

Comments.addView("postCommentsBest", function (terms) {
  return {
    selector: { postId: terms.postId },
    options: {sort: {baseScore: -1}, postedAt: -1}
  };
});

Comments.addView("allRecentComments", function (terms) {
  return {
    options: {sort: {postedAt: -1}, limit: terms.limit || 5},
  };
});

Comments.addView("recentComments", function (terms) {
  return {
    selector: { score:{$gt:0}},
    options: {sort: {postedAt: -1}, limit: terms.limit || 5},
  };
});
Comments.addView("topRecentComments", function (terms) {
  return {
    selector: { score:{$gt:0}, postId:terms.postId},
    options: {sort: {baseScore: -1}, limit: terms.limit || 3},
  };
});

Comments.addView("postCommentsUnread", function (terms) {
  return {
    selector: {
      postId: terms.postId,
    },
    options: {sort: {postedAt: -1}, limit: terms.limit || 5},
  };
});
<|endoftext|>


<commit_before>class ThreddedMentionAutocompletion {
  constructor($) {
    this.$ = $;
    this.textareaSelector = 'textarea';
  }
  init($nodes){
    const $textarea = $nodes.find(this.textareaSelector);
    this.autocompleteMinLength = parseInt($nodes.data('autocompleteMinLength'), 10);
    this.automentionCompletion($textarea, $nodes.data('autocompleteUrl'));
  }

  escapeHtml(text) {
    return this.$('
').text(text).html();
  }

  formatUser({avatar_url, name, escapeHtml}) {
    return "
" +
      `<img class='thredded--select2-user-result__avatar' src='${this.escapeHtml(avatar_url)}' >` +
      `<span class='thredded--select2-user-result__name'>${this.escapeHtml(name)}</span>` +
      '
';
  }

  automentionCompletion($textarea, autocompleteUrl) {
    let mentionAC = this;
    $textarea.textcomplete([{
      match: /(^@|\s@)"?((?:\w| ){1,})$/,
      search (term, callback, match) {
        if(term.length < this.autocompleteMinLength){
          return callback({});
        }
        let termsUrl = `${autocompleteUrl}?q=${term}`;
        $.ajax({url: termsUrl}).done(function (response) {
          callback($.map(response.results, function ({avatar_url, id, name}) {
            return {avatar_url, id, name, match};
          }));
        });
      },
      template ({avatar_url, name}) {
        return mentionAC.formatUser({avatar_url, name});
      },
      replace  ({name, match}) {
        let prefix = match[1];
        if (name.indexOf(" ") > -1) {
          return `${prefix}"${name}" `
        } else {
          return `${prefix}${name} `
        }
      }
    }], {dropdownClassName: 'thredded--textcomplete-dropdown'});
  }
}

<commit_msg>Extract @-mention regexp to a constant<commit_after>class ThreddedMentionAutocompletion {
  constructor($) {
    this.$ = $;
    this.textareaSelector = 'textarea';
  }
  init($nodes){
    const $textarea = $nodes.find(this.textareaSelector);
    this.autocompleteMinLength = parseInt($nodes.data('autocompleteMinLength'), 10);
    this.automentionCompletion($textarea, $nodes.data('autocompleteUrl'));
  }

  escapeHtml(text) {
    return this.$('
').text(text).html();
  }

  formatUser({avatar_url, name, escapeHtml}) {
    return "
" +
      `<img class='thredded--select2-user-result__avatar' src='${this.escapeHtml(avatar_url)}' >` +
      `<span class='thredded--select2-user-result__name'>${this.escapeHtml(name)}</span>` +
      '
';
  }

  automentionCompletion($textarea, autocompleteUrl) {
    let mentionAC = this;
    $textarea.textcomplete([{
      match: ThreddedMentionAutocompletion.MATCH_RE,
      search (term, callback, match) {
        if(term.length < this.autocompleteMinLength){
          return callback({});
        }
        let termsUrl = `${autocompleteUrl}?q=${term}`;
        $.ajax({url: termsUrl}).done(function (response) {
          callback($.map(response.results, function ({avatar_url, id, name}) {
            return {avatar_url, id, name, match};
          }));
        });
      },
      template ({avatar_url, name}) {
        return mentionAC.formatUser({avatar_url, name});
      },
      replace  ({name, match}) {
        let prefix = match[1];
        if (name.indexOf(" ") > -1) {
          return `${prefix}"${name}" `
        } else {
          return `${prefix}${name} `
        }
      }
    }], {dropdownClassName: 'thredded--textcomplete-dropdown'});
  }
}

ThreddedMentionAutocompletion.MATCH_RE = /(^@|\s@)"?((?:\w| )+)$/;
<|endoftext|>


<commit_before>'use strict';

const ember = require('../utils/ember');

//------------------------------------------------------------------------------
// Ember object rule - Avoid leaking state
// (Don't use arrays or objects as default props)
//------------------------------------------------------------------------------

module.exports = {
  meta: {
    docs: {
      description: 'Avoids state leakage',
      category: 'Ember Object',
      recommended: true
    },
    fixable: null, // or "code" or "whitespace"
    schema: [{
      type: 'array',
      items: { type: 'string' },
    }],
  },

  create(context) {
    let ignoredProperties = context.options[0] || [];

    const message = {
      array: 'Avoid using arrays as default properties',
      object: 'Avoid using objects as default properties',
    };

    const report = function (node, messageType) {
      context.report(node, message[messageType]);
    };

    ignoredProperties = ignoredProperties.concat([
      'classNames',
      'classNameBindings',
      'actions',
      'concatenatedProperties',
      'mergedProperties',
      'positionalParams',
      'attributeBindings',
      'queryParams',
    ]);

    return {
      CallExpression(node) {
        if (!ember.isEmberObject(node)) return;

        const properties = ember.getModuleProperties(node);

        properties
          .filter(property => ignoredProperties.indexOf(property.key.name) === -1)
          .forEach((property) => {
            if (ember.isObjectProp(property)) {
              report(property, 'object');
            } else if (ember.isArrayProp(property)) {
              report(property, 'array');
            }
          });
      },
    };
  },
};
<commit_msg>added attrs and queryParams to ignore properties list<commit_after>'use strict';

const ember = require('../utils/ember');

//------------------------------------------------------------------------------
// Ember object rule - Avoid leaking state
// (Don't use arrays or objects as default props)
//------------------------------------------------------------------------------

module.exports = {
  meta: {
    docs: {
      description: 'Avoids state leakage',
      category: 'Ember Object',
      recommended: true
    },
    fixable: null, // or "code" or "whitespace"
    schema: [{
      type: 'array',
      items: { type: 'string' },
    }],
  },

  create(context) {
    let ignoredProperties = context.options[0] || [];

    const message = {
      array: 'Avoid using arrays as default properties',
      object: 'Avoid using objects as default properties',
    };

    const report = function (node, messageType) {
      context.report(node, message[messageType]);
    };

    ignoredProperties = ignoredProperties.concat([
      'classNames',
      'classNameBindings',
      'actions',
      'concatenatedProperties',
      'mergedProperties',
      'positionalParams',
      'attributeBindings',
      'queryParams',
      'attrs',
    ]);

    return {
      CallExpression(node) {
        if (!ember.isEmberObject(node)) return;

        const properties = ember.getModuleProperties(node);

        properties
          .filter(property => ignoredProperties.indexOf(property.key.name) === -1)
          .forEach((property) => {
            if (ember.isObjectProp(property)) {
              report(property, 'object');
            } else if (ember.isArrayProp(property)) {
              report(property, 'array');
            }
          });
      },
    };
  },
};
<|endoftext|>


<commit_before>define(['react', 'singletons/providers', 'singletons/profile',
'collections/sizes', 'components/mixins/modal',
'controllers/providers'], function(React, providers, profile, Sizes,
ModalMixin, ProviderController) {

    var InstanceSizeSelect = React.createClass({
        getInitialState: function() {
            return {
                sizes: null
            };
        },
        updateSizes: function(providerId, identityId) {
            ProviderController.getSizeCollection(providerId, identityId)
                .then(function(newSizes) {
                    this.setState({sizes: newSizes});
                }.bind(this));
        },
        componentDidMount: function() {
            this.updateSizes(this.props.providerId, this.props.identityId);
        },
        componentWillReceiveProps: function(newProps) {
            this.updateSizes(newProps.providerId, newProps.identityId);
        },
        renderOptionText: function(size) {
            return size.get('name');
        },
        render: function() {
            var options = [];
            if (this.state.sizes)
                options = this.state.sizes.map(function(size) {
                    return React.DOM.option({
                        value: size.id
                    }, this.renderOptionText(size));
            }.bind(this));
            return React.DOM.select({
                value: this.props.value,
                className: 'form-control',
                id: 'size',
                onChange: this.props.onChange}, options);
        }
    });

    var IdentitySelect = React.createClass({
        render: function() {
            var options = profile.get('identities').map(function(identity) {
                var provider_name = providers.get(identity.get('provider_id')).get('name');
                return React.DOM.option({value: identity.id},
                    "Identity " + identity.id + " on " + provider_name);
            });
            return React.DOM.select({
                value: this.props.identityId,
                id: 'identity',
                className: 'form-control',
                onChange: this.props.onChange}, options);
        }
    });

    var LaunchApplicationModal = React.createClass({
        mixins: [ModalMixin],
        getInitialState: function() {
            var defaultIdentity = profile.get('identities').at(0);
            return {
                instanceName: '',
                identityId: defaultIdentity.id
            };
        },
        renderTitle: function() {
            return this.props.application.get('name_or_id');
        },
        updateState: function(key, e) {
            var value = e.target.value;
            var state = {};
            state[key] = value;
            this.setState(state);
        },
        renderBody: function() {
            // provider id, identity id, machine_alias, name, size_alias, tags
            var identity = profile.get('identities').get(this.state.identityId);
            return React.DOM.form({role: 'form'},
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'instance-name'}, "Instance Name"),
                    React.DOM.input({type: 'text',
                        className: 'form-control',
                        id: 'instance-name',
                        onChange: _.bind(this.updateState, this, 'instanceName')})),
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'identity'}, "Identity"),
                    IdentitySelect({
                        onChange: _.bind(this.updateState, this, 'identityId'),
                        identityId: this.state.identityId})),
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'size'}, "Instance Size"),
                    InstanceSizeSelect({
                        providerId: identity.get('provider_id'),
                        identityId: identity.id,
                        onChange: _.bind(this.updateState, this, 'sizeId')})));
        },
        launchInstance: function(e) {
            e.preventDefault();
        },
        renderFooter: function() {
            return React.DOM.button({type: 'submit',
                className: 'btn btn-primary',
                onClick: this.launchInstance}, "Launch");
        }
    });

    return LaunchApplicationModal;

});
<commit_msg>Add machine select<commit_after>define(['react', 'singletons/providers', 'singletons/profile',
'collections/sizes', 'components/mixins/modal',
'controllers/providers'], function(React, providers, profile, Sizes,
ModalMixin, ProviderController) {

    var InstanceSizeSelect = React.createClass({
        getInitialState: function() {
            return {
                sizes: null
            };
        },
        updateSizes: function(providerId, identityId) {
            ProviderController.getSizeCollection(providerId, identityId)
                .then(function(newSizes) {
                    this.setState({sizes: newSizes});
                }.bind(this));
        },
        componentDidMount: function() {
            this.updateSizes(this.props.providerId, this.props.identityId);
        },
        componentWillReceiveProps: function(newProps) {
            this.updateSizes(newProps.providerId, newProps.identityId);
        },
        renderOptionText: function(size) {
            return size.get('name');
        },
        render: function() {
            var options = [];
            if (this.state.sizes)
                options = this.state.sizes.map(function(size) {
                    return React.DOM.option({
                        value: size.id
                    }, this.renderOptionText(size));
            }.bind(this));
            return React.DOM.select({
                value: this.props.sizeId,
                className: 'form-control',
                id: 'size',
                onChange: this.props.onChange}, options);
        }
    });

    var IdentitySelect = React.createClass({
        render: function() {
            var options = profile.get('identities').map(function(identity) {
                var provider_name = providers.get(identity.get('provider_id')).get('name');
                return React.DOM.option({value: identity.id},
                    "Identity " + identity.id + " on " + provider_name);
            });
            return React.DOM.select({
                value: this.props.identityId,
                id: 'identity',
                className: 'form-control',
                onChange: this.props.onChange}, options);
        }
    });

    var MachineSelect = React.createClass({
        render: function() {
            var options = this.props.machines.map(function(machine) {
                return React.DOM.option({value: machine.id},
                    machine.get('pretty_version'));
            });
            return React.DOM.select({
                value: this.props.machineId,
                id: 'machine',
                className: 'form-control',
                onChange: this.props.onChange}, options);
        }
    });

    var LaunchApplicationModal = React.createClass({
        mixins: [ModalMixin],
        getInitialState: function() {
            var defaultIdentity = profile.get('identities').at(0);
            return {
                instanceName: '',
                identityId: defaultIdentity.id,
                sizeId: null,
                machineId: this.props.application.get('machines').at(0).id
            };
        },
        renderTitle: function() {
            return this.props.application.get('name_or_id');
        },
        updateState: function(key, e) {
            var value = e.target.value;
            var state = {};
            state[key] = value;
            this.setState(state);
        },
        renderBody: function() {
            // provider id, identity id, machine_alias, name, size_alias, tags
            var identity = profile.get('identities').get(this.state.identityId);
            return React.DOM.form({role: 'form'},
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'instance-name'}, "Instance Name"),
                    React.DOM.input({type: 'text',
                        className: 'form-control',
                        id: 'instance-name',
                        onChange: _.bind(this.updateState, this, 'instanceName')})),
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'identity'}, "Identity"),
                    IdentitySelect({
                        onChange: _.bind(this.updateState, this, 'identityId'),
                        identityId: this.state.identityId})),
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'size'}, "Instance Size"),
                    InstanceSizeSelect({
                        providerId: identity.get('provider_id'),
                        identityId: identity.id,
                        sizeId: this.state.sizeId,
                        onChange: _.bind(this.updateState, this, 'sizeId')})),
                React.DOM.div({className: 'form-group'},
                    React.DOM.label({htmlFor: 'machine'}, "Version"),
                    MachineSelect({
                        machineId: this.state.machineId,
                        machines: this.props.application.get('machines') ,
                        onChange: _.bind(this.updateState, this, 'machineId')})));
        },
        launchInstance: function(e) {
            e.preventDefault();
            console.log(this.state);
        },
        renderFooter: function() {
            return React.DOM.button({type: 'submit',
                className: 'btn btn-primary',
                onClick: this.launchInstance}, "Launch");
        }
    });

    return LaunchApplicationModal;

});
<|endoftext|>