<commit_before>import React from 'react';
import Section from 'shared/components/section/section';

const Gala = () => (

The Operation Code Gala has been postponed. More information is forthcoming.

 We appreciate your patience and continued support.

      {/*

On November 10, 2017, The Operation Code Board of Director and several members of the 3,211 all-volunteer staff attended the Deploy the Future Gala in the Governor Ballroom at Portland’s historic Sentinel Hotel.

At Operation Code, we have grown leaps and bounds since committing the first line of code in 2014. Not long ago, computer coding schools were not accepting the New GI Bill to pay for tuition, room and board. Today, there are ten coding boot camps nationwide accepting U.S. Veterans and the New GI Bill. Lives have been transformed: from veterans attending code schools and building careers in the tech industry to those just being introduced to computer coding.

Through this short and successful journey, we have come to learn that our challenge is significantly larger than we originally understood. The impact we have on these veterans and their families is much broader than we originally envisioned. Today, we are more motivated than ever to expand the bandwidth of Operation Code to provide this continuously growing community of veterans with a skill set that will allow them to become self-sustaining and contribute generously to our society.

The Deploy the Future Gala was a vehicle for us to grow our impact. Attendees helped us in our efforts to ease the transition of our veterans back to civilian life, and contribute to an endowment to provide scholarships to the men and women who have given so much to all of us.

Deploy the Future sponsors were given an opportunity to support a great cause and their organization to civic and military officials; business, tech and community leaders; and our global community of military veterans who are bettering themselves with educational opportunities through Operation Code.

We thank those of you who joined our dedicated team of individuals known as Operation Code as we expand our services, educate our veterans, and Deploy the Future.

          <LinkButton
            text="Join us!"
            theme="red-large"
            link="https://operationcode.ejoinme.org/MyEvents/DeploytheFutureGala2017/DeploytheFutureTicketTableRegistration/tabid/892109/Default.aspx"
            isExternal
          />

Presenting Sponsor $25,000

Name inclusion in the event title “Deploy the Future Gala presented by [NAME here]”

Featured on the cover of the Deploy the Future Gala event catalog

Featured in all event promotional materials

Logo featured on home page of Operation Code website

Two tables at the Gala with prime VIP seating for 16

Full page color ad in program, logo featured throughout event space, acknowledgement in event remarks

Sponsorship of two veterans to attend tech conferences including travel and lodging

Sponsorship of three veterans to Operation Code meetups around the United States

Recognition on Operation Code social media

Blog interview on your company’s involvement with Operation Code

Five Star Sponsor $15,000

Featured on the inside front cover of the Deploy the Future Gala event catalog

Featured in all event promotional materials

Logo featured on home page of Operation Code website

One table at the Gala with prime VIP seating for 8

Full page color ad in the program and acknowledgement in event remarks

Sponsorship of one veteran to a tech conference including travel and lodging

Sponsorship of two veterans to Operation Code meetups around the United States

Recognition on Operation Code social media

Blog interview on your company’s involvement with Operation Code

Four Star Sponsor $10,000

Featured on the inside back cover of the Deploy the Future Gala event catalog

Logo Featured on home page of Operation Code website

One table at the Gala with prime VIP seating for 8

3/4 page color ad in program and acknowledgement in event remarks

Sponsorship of two veterans to Operation Code meetups around the United States

Recognition on Operation Code social media

Blog interview on your company’s involvement with Operation Code

Three Star Sponsor $5,000

Priority seating for 8

1/2 page color ad in the event program

Special recognition in print and web materials

Sponsorship of one veteran to an Operation Code meetup around the United States

Blog interview on your company’s involvement with Operation Code

Scholar Host $2,500

          We know not all of our supporters can make the trip to Portland for the Gala but you can still help by sponsoring the travel and lodging for an Operation Code Veteran Scholar so they can attend Deploy the Future and share their story with our audience. This will provide the scholarship recipient with an incredible networking opportunity. You will be making a tremendous impact on this person’s future.

Specialty Patron of Technology $2,500

          This is an opportunity for an Operation Code supporter to underwrite the technology needs for the Deploy the Future Gala. Operation Code knows the importance of using the right software for the right ask and that is why we are using Greater Giving Online/Mobile Bidding software at our first annual gala.

Patron $1250

Table seating for 8

        <LinkButton
          text="Buy now!"
          theme="red-large"
          link="https://operationcode.ejoinme.org/MyEvents/DeploytheFutureGala2017/DeploytheFutureTicketTableRegistration/tabid/892109/Default.aspx"
          isExternal
        />

Nov 10, 2017

Governor's Ballroom, Sentinel Hotel

Portland, Oregon

 */}

);

export default Gala;
<commit_msg>Fix some typos and edit content slightly<commit_after>import React from 'react';
import Section from 'shared/components/section/section';

const Gala = () => (

The Operation Code Gala has been postponed. More information is forthcoming.

 We appreciate your patience and continued support.

      {/*

On November 10, 2017, The Operation Code Board of Directors and several members of the 3,211 all-volunteer staff attended the Deploy the Future Gala in the Governor Ballroom at Portland’s historic Sentinel Hotel.

At Operation Code, we have grown leaps and bounds since committing the first line of code in 2014. Not long ago, computer coding schools were not accepting the New GI Bill to pay for tuition, room, and board. Today, many coding boot camps nationwide accept U.S. Veterans and the New GI Bill. Lives have been transformed, as veterans attend code schools and build successful careers in the tech industry.

Through this short and successful journey, we have come to learn that our challenge is significantly larger than we originally understood. The impact we have on these veterans and their families is much broader than we originally envisioned. Today, we are more motivated than ever to expand the bandwidth of Operation Code to provide this continuously growing community of veterans with a skill set that will allow them to become self-sustaining and contribute generously to our society.

The Deploy the Future Gala was a vehicle for us to grow our impact. Attendees helped us in our efforts to ease the transition of our veterans back to civilian life, and contribute to an endowment to provide scholarships to the men and women who have given so much to all of us.

Deploy the Future sponsors were given an opportunity to support a great cause and their organization to civic and military officials; business, tech and community leaders; and our global community of military veterans who are bettering themselves with educational opportunities through Operation Code.

We thank those of you who joined our dedicated team of individuals known as Operation Code as we expand our services, educate our veterans, and Deploy the Future.

          <LinkButton
            text="Join us!"
            theme="red-large"
            link="https://operationcode.ejoinme.org/MyEvents/DeploytheFutureGala2017/DeploytheFutureTicketTableRegistration/tabid/892109/Default.aspx"
            isExternal
          />

Presenting Sponsor $25,000

Name inclusion in the event title “Deploy the Future Gala presented by [NAME here]”

Featured on the cover of the Deploy the Future Gala event catalog

Featured in all event promotional materials

Logo featured on home page of Operation Code website

Two tables at the Gala with prime VIP seating for 16

Full page color ad in program, logo featured throughout event space, acknowledgement in event remarks

Sponsorship of two veterans to attend tech conferences including travel and lodging

Sponsorship of three veterans to Operation Code meetups around the United States

Recognition on Operation Code social media

Blog interview on your company’s involvement with Operation Code

Five Star Sponsor $15,000

Featured on the inside front cover of the Deploy the Future Gala event catalog

Featured in all event promotional materials

Logo featured on home page of Operation Code website

One table at the Gala with prime VIP seating for 8

Full page color ad in the program and acknowledgement in event remarks

Sponsorship of one veteran to a tech conference including travel and lodging

Sponsorship of two veterans to Operation Code meetups around the United States

Recognition on Operation Code social media

Blog interview on your company’s involvement with Operation Code

Four Star Sponsor $10,000

Featured on the inside back cover of the Deploy the Future Gala event catalog

Logo Featured on home page of Operation Code website

One table at the Gala with prime VIP seating for 8

3/4 page color ad in program and acknowledgement in event remarks

Sponsorship of two veterans to Operation Code meetups around the United States

Recognition on Operation Code social media

Blog interview on your company’s involvement with Operation Code

Three Star Sponsor $5,000

Priority seating for 8

1/2 page color ad in the event program

Special recognition in print and web materials

Sponsorship of one veteran to an Operation Code meetup around the United States

Blog interview on your company’s involvement with Operation Code

Scholar Host $2,500

          We know not all of our supporters can make the trip to Portland for the Gala but you can still help by sponsoring the travel and lodging for an Operation Code Veteran Scholar so they can attend Deploy the Future and share their story with our audience. This will provide the scholarship recipient with an incredible networking opportunity. You will be making a tremendous impact on this person’s future.

Specialty Patron of Technology $2,500

          This is an opportunity for an Operation Code supporter to underwrite the technology needs for the Deploy the Future Gala. Operation Code knows the importance of using the right software for the right ask and that is why we are using Greater Giving Online/Mobile Bidding software at our first annual gala.

Patron $1250

Table seating for 8

        <LinkButton
          text="Buy now!"
          theme="red-large"
          link="https://operationcode.ejoinme.org/MyEvents/DeploytheFutureGala2017/DeploytheFutureTicketTableRegistration/tabid/892109/Default.aspx"
          isExternal
        />

Nov 10, 2017

Governor's Ballroom, Sentinel Hotel

Portland, Oregon

 */}

);

export default Gala;
<|endoftext|>


<commit_before>/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
 * text of the license. */

/**
 * @class
 *
 * @requires OpenLayers/Control.js
 */
OpenLayers.Control.MousePosition = OpenLayers.Class.create();
OpenLayers.Control.MousePosition.prototype =
  OpenLayers.Class.inherit( OpenLayers.Control, {

    /** @type DOMElement */
    element: null,

    /** @type String */
    prefix: '',

    /** @type String */
    separator: ', ',

    /** @type String */
    suffix: '',

    /** @type int */
    numdigits: 5,

    /** @type int */
    granularity: 1,

    /** @type OpenLayers.LonLat */
    lastXy: null,

    /**
     * @constructor
     *
     * @param {DOMElement} options Options for control.
     */
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    /**
     * @type DOMElement
     */
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this, arguments);

        if (!this.element) {
            this.div.left = "";
            this.div.top = "";
            this.div.className = "olControlMousePosition";
            this.element = this.div;
        }

        this.redraw();
        return this.div;
    },

    /**
     *
     */
    redraw: function(evt) {

        var lonLat;

        if (evt == null) {
            lonLat = new OpenLayers.LonLat(0, 0);
        } else {
            if (this.lastXy == null ||
                Math.abs(evt.xy.x - this.lastXy.x) > this.granularity ||
                Math.abs(evt.xy.y - this.lastXy.y) > this.granularity)
            {
                this.lastXy = evt.xy;
                return;
            }

            lonLat = this.map.getLonLatFromPixel(evt.xy);
            this.lastXy = evt.xy;
        }

        var digits = parseInt(this.numdigits);
        var newHtml =
            this.prefix +
            lonLat.lon.toFixed(digits) +
            this.separator +
            lonLat.lat.toFixed(digits) +
            this.suffix;

        if (newHtml != this.element.innerHTML) {
            this.element.innerHTML = newHtml;
        }
    },

    /**
     *
     */
    setMap: function() {
        OpenLayers.Control.prototype.setMap.apply(this, arguments);
        this.map.events.register( 'mousemove', this, this.mousemove);
    },

    /** @final @type String */
    CLASS_NAME: "OpenLayers.Control.MousePosition"
});
<commit_msg>Consistency is key. Mousmove->redraw in remaining location.<commit_after>/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
 * text of the license. */

/**
 * @class
 *
 * @requires OpenLayers/Control.js
 */
OpenLayers.Control.MousePosition = OpenLayers.Class.create();
OpenLayers.Control.MousePosition.prototype =
  OpenLayers.Class.inherit( OpenLayers.Control, {

    /** @type DOMElement */
    element: null,

    /** @type String */
    prefix: '',

    /** @type String */
    separator: ', ',

    /** @type String */
    suffix: '',

    /** @type int */
    numdigits: 5,

    /** @type int */
    granularity: 1,

    /** @type OpenLayers.LonLat */
    lastXy: null,

    /**
     * @constructor
     *
     * @param {DOMElement} options Options for control.
     */
    initialize: function(options) {
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
    },

    /**
     * @type DOMElement
     */
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this, arguments);

        if (!this.element) {
            this.div.left = "";
            this.div.top = "";
            this.div.className = "olControlMousePosition";
            this.element = this.div;
        }

        this.redraw();
        return this.div;
    },

    /**
     *
     */
    redraw: function(evt) {

        var lonLat;

        if (evt == null) {
            lonLat = new OpenLayers.LonLat(0, 0);
        } else {
            if (this.lastXy == null ||
                Math.abs(evt.xy.x - this.lastXy.x) > this.granularity ||
                Math.abs(evt.xy.y - this.lastXy.y) > this.granularity)
            {
                this.lastXy = evt.xy;
                return;
            }

            lonLat = this.map.getLonLatFromPixel(evt.xy);
            this.lastXy = evt.xy;
        }

        var digits = parseInt(this.numdigits);
        var newHtml =
            this.prefix +
            lonLat.lon.toFixed(digits) +
            this.separator +
            lonLat.lat.toFixed(digits) +
            this.suffix;

        if (newHtml != this.element.innerHTML) {
            this.element.innerHTML = newHtml;
        }
    },

    /**
     *
     */
    setMap: function() {
        OpenLayers.Control.prototype.setMap.apply(this, arguments);
        this.map.events.register( 'mousemove', this, this.redraw);
    },

    /** @final @type String */
    CLASS_NAME: "OpenLayers.Control.MousePosition"
});
<|endoftext|>


<commit_before>/**
 * forceDirectedLayout.js
 *
 * This module contains logic for performing the force-directed layout
 * algorithm on a graph.
 *
 * @author John O'Brien.
 */

var CardinalPortPosition = require('./../model/layout/cardinalPortPosition');
var CardinalDirection = require('../enum/cardinalDirection');

var change = false;
//ideal length
var iLength = 500;
//force strength
var forceStr = 1 / 3;
//stretching force
var stretchForce = 0.70;
var vertices;
var mGraph;

/**
 * Takes an edge and returns its length's y value
 *
 * Returns nothing
 *
 * @method edgeYLength
 * @param  {edge} edge
 * @return {int} length
 */
var edgeYLength = function(edge) {
  var to = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var from = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));

  var y = to.getLayout().get('position').y - from.getLayout().get('position').y;
  return y;
};

/**
 * Takes an edge and returns its length's x value
 *
 * Returns nothing
 *
 * @method edgeXLength
 * @param  {edge} edge
 * @return {int} length
 */
var edgeXLength = function(edge) {
  var to = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var from = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));

  var x = to.getLayout().get('position').x - from.getLayout().get('position').x;
  return x;

};

//calculates edge length
/**
 * Takes an edge and returns its length
 *
 * Returns nothing
 *
 * @method edgeLength
 * @param  {edge} edge
 * @return {int} length
 */

var edgeLength = function(edge) {
  var toLayout = mGraph.getVertexById(edge.get('to').get('ownerVertexId')).getLayout();
  var fromLayout = mGraph.getVertexById(edge.get('from').get('ownerVertexId')).getLayout();

  //pythag theorem
  var x = toLayout.get('position').x - fromLayout.get('position').x;
  var y = toLayout.get('position').y - fromLayout.get('position').y;
  var c = x * x + y * y;

  return Math.sqrt(c);
};

/**
 * Takes an edge and calculates the repulsion for that edge
 *
 * Returns nothing
 *
 * @method springForce
 * @param  {edge} edge
 * @return nothing
 */

var springForce = function(edge) {
  //vertex to
  var vertexTo = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var vertexToLayout = vertexTo.getLayout();
  var vertexToPinned = vertexToLayout.get('isPinned');

  //vertex from
  var vertexFrom = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));
  var vertexFromLayout = vertexFrom.getLayout();
  var vertexFromPinned = vertexFromLayout.get('isPinned');

  //x distance between them
  var xLength = edgeXLength(edge);
  //y distance between them
  var yLength = edgeYLength(edge);
  //straight line edge length
  var length = edgeLength(edge);
  //checks for both pinned
  if (vertexToPinned && vertexFromPinned) {
    return;
  }

  //hacky solution for length being 0
  if (length === 0) {
    length = 0.99;
  }
  //repulsion force calculation
  var force = forceStr * (iLength - length) / length;
  var pwrTo = vertexTo.get('inputs').length + vertexTo.get('outputs').length;
  var pwrFr = vertexFrom.get('inputs').length + vertexFrom.get('outputs').length;
  force = force * Math.pow(stretchForce, (pwrTo + pwrFr - 4));

  //repulsion change in x
  var repulsionX = force * xLength;
  //repulsion change in y
  var repulsionY = force * yLength;
  //attraction x
  var attractionX;
  //attraction y
  var attractionY;
  //math for min length
  if (length < 1) {
    attractionX = Math.random() * 10 + 1;
    attractionY = Math.random() * 10 + 1;
  } else {
    attractionX = xLength / (length * length);
    attractionY = yLength / (length * length);
  }
  var len = attractionX * attractionX + attractionY * attractionY;
  //ensures length is positive
  if (len > 0) {
    len = Math.sqrt(len);
    attractionX = attractionX / len;
    attractionY = attractionY / len;
  }
  //repulsion minus attraction
  repulsionX = repulsionX - attractionX;
  repulsionY = repulsionY - attractionY;

  //the minimum movement percentage to consider a move a change
  //constant can be altered for desired effects (higher means less runs lower will
  //be more accurate)
  var minLimit = 0.1;

  if (vertexToPinned === false && vertexFromPinned === false) {
    vertexToLayout.set('position', {
      'x': (vertexToLayout.get('position').x + repulsionX),
      'y': (vertexToLayout.get('position').y + repulsionY)
    });
    vertexFromLayout.set('position', {
      'x': vertexFromLayout.get('position').x - repulsionX,
      'y': vertexFromLayout.get('position').y - repulsionY
    });
  } else if (vertexToPinned === true) {
    vertexFromLayout.set('position', {
      'x': vertexFromLayout.get('position').x - repulsionX - repulsionX,
      'y': vertexFromLayout.get('position').y - repulsionY - repulsionY
    });

  } else if (vertexFromPinned === true) {
    vertexToLayout.set('position', {
      'x': (vertexToLayout.get('position').x + repulsionX + repulsionX),
      'y': (vertexToLayout.get('position').y + repulsionY + repulsionY)
    });
  }
  if (repulsionX > minLimit || repulsionY > minLimit || (repulsionX < -minLimit) || (repulsionY < -minLimit)) {
    change = true;
  }
};

//Based partially on https://code.google.com/p/jung/source/browse/branches/
//guava/jung/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/
//layout/SpringLayout.java?r=19

/**
 * Defines force directed layout algorithm
 *
 * @class forceDirectedLayout
 *
 */

/**
 * Takes the graph and re aligns the nodes
 *
 * Returns nothing
 *
 * @method layOutGraph
 * @param  {Graph} graph
 * @return nothing
 */

var layOutGraph = function(graph) {
  mGraph = graph;
  vertices = graph.get('vertices');
  var edgeList = graph.get('edges');
  var runner = true;
  while (runner) {
    change = false;
    for (var i = 0; i < edgeList.length; i++) {
      springForce(edgeList[i]);
    }
    if (change === false) {
      runner = false;
    }
  }
  //defaulting all ports that do not have a position
  for (var j = 0; j < vertices.length; j++) {
    var inputs = vertices[j].get('inputs');
    var outputs = vertices[j].get('outputs');

    for (var h = 0; h < inputs.length; h++) {
      if (inputs[h].getLayout().get('position') === null) {
        inputs[h].getLayout().set('position', new CardinalPortPosition(CardinalDirection.EAST, 50));
      }
    }

    for (h = 0; h < outputs.length; h++) {
      if (outputs[h].getLayout().get('position') === null) {
        outputs[h].getLayout().set('position', new CardinalPortPosition(CardinalDirection.WEST, 50));
      }
    }
  }
};

/* not yet implemented
function portPositioning(edge){
  var vertexTo = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var vertexFrom = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));
  var xLength = edgeXLength(edge);
  var yLength = edgeYLength(edge);
}*/

module.exports = layOutGraph;
<commit_msg>Clean up<commit_after>/**
 * forceDirectedLayout.js
 *
 * This module contains logic for performing the force-directed layout
 * algorithm on a graph.
 *
 * @author John O'Brien.
 */

var CardinalPortPosition = require('./../model/layout/cardinalPortPosition');
var CardinalDirection = require('../enum/cardinalDirection');
var ObjectUtils = require('../utilities/objects');

var change = false;
//ideal length
var iLength = 500;
//force strength
var forceStr = 1 / 3;
//stretching force
var stretchForce = 0.70;
var vertices;
var mGraph;

/**
 * Takes an edge and returns its length's y value
 *
 * Returns nothing
 *
 * @method edgeYLength
 * @param  {edge} edge
 * @return {int} length
 */
var edgeYLength = function(edge) {
  var to = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var from = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));

  var y = to.getLayout().get('position').y - from.getLayout().get('position').y;
  return y;
};

/**
 * Takes an edge and returns its length's x value
 *
 * Returns nothing
 *
 * @method edgeXLength
 * @param  {edge} edge
 * @return {int} length
 */
var edgeXLength = function(edge) {
  var to = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var from = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));

  var x = to.getLayout().get('position').x - from.getLayout().get('position').x;
  return x;

};

//calculates edge length
/**
 * Takes an edge and returns its length
 *
 * Returns nothing
 *
 * @method edgeLength
 * @param  {edge} edge
 * @return {int} length
 */

var edgeLength = function(edge) {
  var toLayout = mGraph.getVertexById(edge.get('to').get('ownerVertexId')).getLayout();
  var fromLayout = mGraph.getVertexById(edge.get('from').get('ownerVertexId')).getLayout();

  //pythag theorem
  var x = toLayout.get('position').x - fromLayout.get('position').x;
  var y = toLayout.get('position').y - fromLayout.get('position').y;
  var c = x * x + y * y;

  return Math.sqrt(c);
};

/**
 * Takes an edge and calculates the repulsion for that edge
 *
 * Returns nothing
 *
 * @method springForce
 * @param  {edge} edge
 * @return nothing
 */

var springForce = function(edge) {
  //vertex to
  var vertexTo = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var vertexToLayout = vertexTo.getLayout();
  var vertexToPinned = vertexToLayout.get('isPinned');

  //vertex from
  var vertexFrom = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));
  var vertexFromLayout = vertexFrom.getLayout();
  var vertexFromPinned = vertexFromLayout.get('isPinned');

  //x distance between them
  var xLength = edgeXLength(edge);
  //y distance between them
  var yLength = edgeYLength(edge);
  //straight line edge length
  var length = edgeLength(edge);
  //checks for both pinned
  if (vertexToPinned && vertexFromPinned) {
    return;
  }

  //hacky solution for length being 0
  if (length === 0) {
    length = 0.99;
  }
  //repulsion force calculation
  var force = forceStr * (iLength - length) / length;
  var pwrTo = vertexTo.get('inputs').length + vertexTo.get('outputs').length;
  var pwrFr = vertexFrom.get('inputs').length + vertexFrom.get('outputs').length;
  force = force * Math.pow(stretchForce, (pwrTo + pwrFr - 4));

  //repulsion change in x
  var repulsionX = force * xLength;
  //repulsion change in y
  var repulsionY = force * yLength;

  //attraction x
  var attractionX;
  //attraction y
  var attractionY;
  //math for min length
  if (length < 1) {
    attractionX = Math.random() * 10 + 1;
    attractionY = Math.random() * 10 + 1;
  } else {
    attractionX = xLength / (length * length);
    attractionY = yLength / (length * length);
  }
  var len = attractionX * attractionX + attractionY * attractionY;
  //ensures length is positive
  if (len > 0) {
    len = Math.sqrt(len);
    attractionX = attractionX / len;
    attractionY = attractionY / len;
  }

  //repulsion minus attraction
  repulsionX = repulsionX - attractionX;
  repulsionY = repulsionY - attractionY;

  //the minimum movement percentage to consider a move a change
  //constant can be altered for desired effects (higher means less runs lower will
  //be more accurate)
  var minLimit = 0.1;

  var addRepulsion = function(layout) {
    var newPos = ObjectUtils.merge(layout.get('position'));
    newPos.x += repulsionX;
    newPos.y += repulsionY;
    layout.set('position', newPos);
  };

  var subtractRepulsion = function(layout) {
    var newPos = ObjectUtils.merge(layout.get('position'));
    newPos.x -= repulsionX;
    newPos.y -= repulsionY;
    layout.set('position', newPos);
  };

  if (!vertexToPinned) {
    addRepulsion(vertexToLayout);
  }
  if (!vertexFromPinned) {
    subtractRepulsion(vertexFromLayout);
  }

  change = repulsionX > minLimit || repulsionY > minLimit || (repulsionX < -minLimit) || (repulsionY < -minLimit);
};

//Based partially on https://code.google.com/p/jung/source/browse/branches/
//guava/jung/jung-algorithms/src/main/java/edu/uci/ics/jung/algorithms/
//layout/SpringLayout.java?r=19

/**
 * Defines force directed layout algorithm
 *
 * @class forceDirectedLayout
 *
 */

/**
 * Takes the graph and re aligns the nodes
 *
 * Returns nothing
 *
 * @method layOutGraph
 * @param  {Graph} graph
 * @return nothing
 */

var layOutGraph = function(graph) {
  mGraph = graph;
  vertices = graph.get('vertices');
  var edgeList = graph.get('edges');
  var runner = true;
  while (runner) {
    change = false;
    for (var i = 0; i < edgeList.length; i++) {
      springForce(edgeList[i]);
    }
    if (change === false) {
      runner = false;
    }
  }
  //defaulting all ports that do not have a position
  for (var j = 0; j < vertices.length; j++) {
    var inputs = vertices[j].get('inputs');
    var outputs = vertices[j].get('outputs');

    for (var h = 0; h < inputs.length; h++) {
      if (inputs[h].getLayout().get('position') === null) {
        inputs[h].getLayout().set('position', new CardinalPortPosition(CardinalDirection.EAST, 50));
      }
    }

    for (h = 0; h < outputs.length; h++) {
      if (outputs[h].getLayout().get('position') === null) {
        outputs[h].getLayout().set('position', new CardinalPortPosition(CardinalDirection.WEST, 50));
      }
    }
  }
};

/* not yet implemented
function portPositioning(edge){
  var vertexTo = mGraph.getVertexById(edge.get('to').get('ownerVertexId'));
  var vertexFrom = mGraph.getVertexById(edge.get('from').get('ownerVertexId'));
  var xLength = edgeXLength(edge);
  var yLength = edgeYLength(edge);
}*/

module.exports = layOutGraph;
<|endoftext|>


<commit_before>'use strict';

var normalizeOptions  = require('es5-ext/object/normalize-options')
  , setPrototypeOf    = require('es5-ext/object/set-prototype-of')
  , ensureString      = require('es5-ext/object/validate-stringifiable-value')
  , ensureObject      = require('es5-ext/object/valid-object')
  , resolveKeyPath    = require('dbjs/_setup/utils/resolve-key-path')
  , rmdir             = require('fs2/rmdir')
  , d                 = require('d')
  , deferred          = require('deferred')
  , level             = require('levelup')
  , PersistenceDriver = require('dbjs-persistence/abstract')

  , isArray = Array.isArray, create = Object.create, stringify = JSON.stringify
  , parse = JSON.parse, promisify = deferred.promisify
  , getOpts = { fillCache: false };

var LevelDriver = module.exports = function (dbjs, data) {
	if (!(this instanceof LevelDriver)) return new LevelDriver(dbjs, data);
	this._dbOptions = normalizeOptions(ensureObject(data));
	// Below is workaround for https://github.com/Raynos/xtend/pull/28
	this._dbOptions.hasOwnProperty = Object.prototype.hasOwnProperty;
	this._dbOptions.path = ensureString(this._dbOptions.path);
	PersistenceDriver.call(this, dbjs, data);
	this._initialize();
};
setPrototypeOf(LevelDriver, PersistenceDriver);

LevelDriver.prototype = Object.create(PersistenceDriver.prototype, {
	constructor: d(LevelDriver),

	// Any data
	__getRaw: d(function (cat, ns, path) {
		if (cat === 'reduced') return this._getReduced(ns + (path ? ('/' + path) : ''));
		if (cat === 'computed') return this._getIndexedValue(path, ns);
		return this.levelDb.getPromised(ns + (path ? ('/' + path) : ''), getOpts)(function (value) {
			var index = value.indexOf('.');
			return { stamp: Number(value.slice(0, index)), value: value.slice(index + 1) };
		}.bind(this), function (err) {
			if (err.notFound) return null;
			throw err;
		});
	}),
	__getDirectObject: d(function (objId, keyPaths) {
		return this._loadDirect({ gte: objId, lte: objId + '/\uffff' },
			keyPaths && function (ownerId, path) { return keyPaths.has(resolveKeyPath(path)); });
	}),
	__storeRaw: d(function (cat, ns, path, data) {
		if (cat === 'reduced') return this._storeReduced(ns + (path ? ('/' + path) : ''), data);
		if (cat === 'computed') return this._storeIndexedValue(path, ns, data);
		return this.levelDb.putPromised(ns + (path ? ('/' + path) : ''), data.stamp + '.' + data.value);
	}),

	// Database data
	__getDirectAll: d(function () { return this._loadDirect(); }),

	// Size tracking
	__searchDirect: d(function (callback) {
		var def = deferred();
		this.levelDb.createReadStream().on('data', function (data) {
			var index;
			if (data.key[0] === '=') return; // computed record
			if (data.key[0] === '_') return; // reduced record
			index = data.value.indexOf('.');
			callback(data.key, {
				stamp: Number(data.value.slice(0, index)),
				value: data.value.slice(index + 1)
			});
		}.bind(this)).on('error', def.reject).on('end', def.resolve);
		return def.promise;
	}),
	__searchComputed: d(function (keyPath, callback) {
		var def = deferred();
		this.levelDb.createReadStream({ gte: '=' + keyPath + ':', lte: '=' + keyPath + ':\uffff' })
			.on('data', function (data) {
				var index, value, ownerId = data.key.slice(data.key.lastIndexOf(':') + 1);
				index = data.value.indexOf('.');
				value = data.value.slice(index + 1);
				if (value[0] === '[') value = parse(value);
				callback(ownerId, { value: value, stamp: Number(data.value.slice(0, index)) });
			}.bind(this)).on('error', def.reject).on('end', def.resolve);
		return def.promise;
	}),

	// Reduced data
	__getReducedNs: d(function (ns, keyPaths) {
		var def, result;
		def = deferred();
		result = create(null);
		this.levelDb.createReadStream({ gte: '_' + ns, lte: '_' + ns + '/\uffff' })
			.on('data', function (data) {
				var index, path;
				if (keyPaths) {
					index = data.key.indexOf('/');
					path = (index !== -1) ? data.key.slice(index + 1) : null;
					if (!keyPaths.has(path)) return; // filtered
				}
				index = data.value.indexOf('.');
				result[data.key.slice(1)] = {
					stamp: Number(data.value.slice(0, index)),
					value: data.value.slice(index + 1)
				};
			}.bind(this)).on('error', def.reject).on('end', function () { def.resolve(result); });
		return def.promise;
	}),

	// Storage import/export
	__exportAll: d(function (destDriver) {
		var def, promises = [], count = 0;
		def = deferred();
		this.levelDb.createReadStream().on('data', function (record) {
			var index, id, cat, ns, path, data;
			if (!(++count % 1000)) def.promise.emit('progress');
			index = record.value.indexOf('.');
			data = {
				value: record.value.slice(index + 1),
				stamp: Number(record.value.slice(0, index))
			};
			if (record.key[0] === '=') {
				cat = 'computed';
				id = record.key.slice(1);
				index = id.lastIndexOf(':');
				ns = id.slice(0, index);
				path = id.slice(index + 1);
			} else {
				if (record.key[0] === '_') {
					cat = 'reduced';
					id = record.key.slice(1);
				} else {
					id = record.key;
					cat = 'direct';
				}
				index = id.indexOf('/');
				ns = (index === -1) ? id : id.slice(0, index);
				path = (index === -1) ? null : id.slice(index + 1);
			}
			promises.push(destDriver.__storeRaw(cat, ns, path, data));
		}.bind(this)).on('error', function (err) { def.reject(err); }).on('end', function () {
			def.resolve(deferred.map(promises));
		});
		return def.promise;
	}),
	__clear: d(function () {
		return this.__close()(function () {
			return rmdir(this._dbOptions.path, { recursive: true, force: true })(function () {
				this._initialize();
			}.bind(this));
		}.bind(this));
	}),

	// Connection related
	__close: d(function () { return this.levelDb.closePromised(); }),

	// Driver specific
	_getIndexedValue: d(function (objId, keyPath) {
		return this.levelDb.getPromised('=' + keyPath + ':' + objId, getOpts)(function (data) {
			var index = data.indexOf('.'), value = data.slice(index + 1);
			if (value[0] === '[') value = parse(value);
			return { value: value, stamp: Number(data.slice(0, index)) };
		}.bind(this), function (err) {
			if (err.notFound) return null;
			throw err;
		});
	}),
	_storeIndexedValue: d(function (objId, keyPath, data) {
		return this.levelDb.putPromised('=' + keyPath + ':' + objId,
			data.stamp + '.' + (isArray(data.value) ? stringify(data.value) : data.value));
	}),
	_getReduced: d(function (key) {
		return this.levelDb.getPromised('_' + key, getOpts)(function (value) {
			var index = value.indexOf('.');
			return { stamp: Number(value.slice(0, index)), value: value.slice(index + 1) };
		}, function (err) {
			if (err.notFound) return;
			throw err;
		});
	}),
	_storeReduced: d(function (key, data) {
		return this.levelDb.putPromised('_' + key, data.stamp + '.' + data.value);
	}),
	_loadDirect: d(function (data, filter) {
		var def, result;
		def = deferred();
		result = create(null);
		this.levelDb.createReadStream(data).on('data', function (data) {
			var index, ownerId, path;
			if (data.key[0] === '=') return; // computed record
			if (data.key[0] === '_') return; // reduced record
			if (filter) {
				index = data.key.indexOf('/');
				ownerId = (index !== -1) ? data.key.slice(0, index) : data.key;
				path = (index !== -1) ? data.key.slice(index + 1) : null;
				if (!filter(ownerId, path)) return; // filtered
			}
			index = data.value.indexOf('.');
			result[data.key] = {
				stamp: Number(data.value.slice(0, index)),
				value: data.value.slice(index + 1)
			};
		}.bind(this)).on('error', def.reject).on('end', function () { def.resolve(result); });
		return def.promise;
	}),
	_initialize: d(function () {
		var db = this.levelDb = level(this._dbOptions.path, this._dbOptions);
		db.getPromised = promisify(db.get);
		db.putPromised = promisify(db.put);
		db.delPromised = promisify(db.del);
		db.batchPromised = promisify(db.batch);
		db.closePromised = promisify(db.close);
	})
});
<commit_msg>Rename _getIndexedValue into _getComputedValue<commit_after>'use strict';

var normalizeOptions  = require('es5-ext/object/normalize-options')
  , setPrototypeOf    = require('es5-ext/object/set-prototype-of')
  , ensureString      = require('es5-ext/object/validate-stringifiable-value')
  , ensureObject      = require('es5-ext/object/valid-object')
  , resolveKeyPath    = require('dbjs/_setup/utils/resolve-key-path')
  , rmdir             = require('fs2/rmdir')
  , d                 = require('d')
  , deferred          = require('deferred')
  , level             = require('levelup')
  , PersistenceDriver = require('dbjs-persistence/abstract')

  , isArray = Array.isArray, create = Object.create, stringify = JSON.stringify
  , parse = JSON.parse, promisify = deferred.promisify
  , getOpts = { fillCache: false };

var LevelDriver = module.exports = function (dbjs, data) {
	if (!(this instanceof LevelDriver)) return new LevelDriver(dbjs, data);
	this._dbOptions = normalizeOptions(ensureObject(data));
	// Below is workaround for https://github.com/Raynos/xtend/pull/28
	this._dbOptions.hasOwnProperty = Object.prototype.hasOwnProperty;
	this._dbOptions.path = ensureString(this._dbOptions.path);
	PersistenceDriver.call(this, dbjs, data);
	this._initialize();
};
setPrototypeOf(LevelDriver, PersistenceDriver);

LevelDriver.prototype = Object.create(PersistenceDriver.prototype, {
	constructor: d(LevelDriver),

	// Any data
	__getRaw: d(function (cat, ns, path) {
		if (cat === 'reduced') return this._getReduced(ns + (path ? ('/' + path) : ''));
		if (cat === 'computed') return this._getComputedValue(path, ns);
		return this.levelDb.getPromised(ns + (path ? ('/' + path) : ''), getOpts)(function (value) {
			var index = value.indexOf('.');
			return { stamp: Number(value.slice(0, index)), value: value.slice(index + 1) };
		}.bind(this), function (err) {
			if (err.notFound) return null;
			throw err;
		});
	}),
	__getDirectObject: d(function (objId, keyPaths) {
		return this._loadDirect({ gte: objId, lte: objId + '/\uffff' },
			keyPaths && function (ownerId, path) { return keyPaths.has(resolveKeyPath(path)); });
	}),
	__storeRaw: d(function (cat, ns, path, data) {
		if (cat === 'reduced') return this._storeReduced(ns + (path ? ('/' + path) : ''), data);
		if (cat === 'computed') return this._storeIndexedValue(path, ns, data);
		return this.levelDb.putPromised(ns + (path ? ('/' + path) : ''), data.stamp + '.' + data.value);
	}),

	// Database data
	__getDirectAll: d(function () { return this._loadDirect(); }),

	// Size tracking
	__searchDirect: d(function (callback) {
		var def = deferred();
		this.levelDb.createReadStream().on('data', function (data) {
			var index;
			if (data.key[0] === '=') return; // computed record
			if (data.key[0] === '_') return; // reduced record
			index = data.value.indexOf('.');
			callback(data.key, {
				stamp: Number(data.value.slice(0, index)),
				value: data.value.slice(index + 1)
			});
		}.bind(this)).on('error', def.reject).on('end', def.resolve);
		return def.promise;
	}),
	__searchComputed: d(function (keyPath, callback) {
		var def = deferred();
		this.levelDb.createReadStream({ gte: '=' + keyPath + ':', lte: '=' + keyPath + ':\uffff' })
			.on('data', function (data) {
				var index, value, ownerId = data.key.slice(data.key.lastIndexOf(':') + 1);
				index = data.value.indexOf('.');
				value = data.value.slice(index + 1);
				if (value[0] === '[') value = parse(value);
				callback(ownerId, { value: value, stamp: Number(data.value.slice(0, index)) });
			}.bind(this)).on('error', def.reject).on('end', def.resolve);
		return def.promise;
	}),

	// Reduced data
	__getReducedNs: d(function (ns, keyPaths) {
		var def, result;
		def = deferred();
		result = create(null);
		this.levelDb.createReadStream({ gte: '_' + ns, lte: '_' + ns + '/\uffff' })
			.on('data', function (data) {
				var index, path;
				if (keyPaths) {
					index = data.key.indexOf('/');
					path = (index !== -1) ? data.key.slice(index + 1) : null;
					if (!keyPaths.has(path)) return; // filtered
				}
				index = data.value.indexOf('.');
				result[data.key.slice(1)] = {
					stamp: Number(data.value.slice(0, index)),
					value: data.value.slice(index + 1)
				};
			}.bind(this)).on('error', def.reject).on('end', function () { def.resolve(result); });
		return def.promise;
	}),

	// Storage import/export
	__exportAll: d(function (destDriver) {
		var def, promises = [], count = 0;
		def = deferred();
		this.levelDb.createReadStream().on('data', function (record) {
			var index, id, cat, ns, path, data;
			if (!(++count % 1000)) def.promise.emit('progress');
			index = record.value.indexOf('.');
			data = {
				value: record.value.slice(index + 1),
				stamp: Number(record.value.slice(0, index))
			};
			if (record.key[0] === '=') {
				cat = 'computed';
				id = record.key.slice(1);
				index = id.lastIndexOf(':');
				ns = id.slice(0, index);
				path = id.slice(index + 1);
			} else {
				if (record.key[0] === '_') {
					cat = 'reduced';
					id = record.key.slice(1);
				} else {
					id = record.key;
					cat = 'direct';
				}
				index = id.indexOf('/');
				ns = (index === -1) ? id : id.slice(0, index);
				path = (index === -1) ? null : id.slice(index + 1);
			}
			promises.push(destDriver.__storeRaw(cat, ns, path, data));
		}.bind(this)).on('error', function (err) { def.reject(err); }).on('end', function () {
			def.resolve(deferred.map(promises));
		});
		return def.promise;
	}),
	__clear: d(function () {
		return this.__close()(function () {
			return rmdir(this._dbOptions.path, { recursive: true, force: true })(function () {
				this._initialize();
			}.bind(this));
		}.bind(this));
	}),

	// Connection related
	__close: d(function () { return this.levelDb.closePromised(); }),

	// Driver specific
	_getComputedValue: d(function (objId, keyPath) {
		return this.levelDb.getPromised('=' + keyPath + ':' + objId, getOpts)(function (data) {
			var index = data.indexOf('.'), value = data.slice(index + 1);
			if (value[0] === '[') value = parse(value);
			return { value: value, stamp: Number(data.slice(0, index)) };
		}.bind(this), function (err) {
			if (err.notFound) return null;
			throw err;
		});
	}),
	_storeIndexedValue: d(function (objId, keyPath, data) {
		return this.levelDb.putPromised('=' + keyPath + ':' + objId,
			data.stamp + '.' + (isArray(data.value) ? stringify(data.value) : data.value));
	}),
	_getReduced: d(function (key) {
		return this.levelDb.getPromised('_' + key, getOpts)(function (value) {
			var index = value.indexOf('.');
			return { stamp: Number(value.slice(0, index)), value: value.slice(index + 1) };
		}, function (err) {
			if (err.notFound) return;
			throw err;
		});
	}),
	_storeReduced: d(function (key, data) {
		return this.levelDb.putPromised('_' + key, data.stamp + '.' + data.value);
	}),
	_loadDirect: d(function (data, filter) {
		var def, result;
		def = deferred();
		result = create(null);
		this.levelDb.createReadStream(data).on('data', function (data) {
			var index, ownerId, path;
			if (data.key[0] === '=') return; // computed record
			if (data.key[0] === '_') return; // reduced record
			if (filter) {
				index = data.key.indexOf('/');
				ownerId = (index !== -1) ? data.key.slice(0, index) : data.key;
				path = (index !== -1) ? data.key.slice(index + 1) : null;
				if (!filter(ownerId, path)) return; // filtered
			}
			index = data.value.indexOf('.');
			result[data.key] = {
				stamp: Number(data.value.slice(0, index)),
				value: data.value.slice(index + 1)
			};
		}.bind(this)).on('error', def.reject).on('end', function () { def.resolve(result); });
		return def.promise;
	}),
	_initialize: d(function () {
		var db = this.levelDb = level(this._dbOptions.path, this._dbOptions);
		db.getPromised = promisify(db.get);
		db.putPromised = promisify(db.put);
		db.delPromised = promisify(db.del);
		db.batchPromised = promisify(db.batch);
		db.closePromised = promisify(db.close);
	})
});
<|endoftext|>


<commit_before>import store2 from 'store2';
import EventEmitter from 'events';

const STORE_NAMESPACE = 'soundboard';

const DEFAULT_SETTINGS = {
  volume: 1.0,
  theme: 'default',
};

export const settingManifest = {
  volume: {
    label: 'Volume',
    type: 'slider',
    params: { min: 0, max: 100, step: 10, multiplier: 100 },
  },
  theme: {
    label: 'Theme',
    type: 'theme',
  },
};

class SettingsManager extends EventEmitter {

  /** @type SettingsManager */
  static instance;

  store;

  static init() {
    this.instance = new SettingsManager();
  }

  constructor() {
    super();

    // Init store with namespace
    this.store = store2.namespace(STORE_NAMESPACE);
    // Set default settings, without overwrite
    this.store.setAll(DEFAULT_SETTINGS, false);
  }

  set(key, value, overwrite = true) {
    this.store.set(key, value, overwrite);

    this.emit(key, value);
  }

  get(key) {
    return this.store.get(key);
  }

  getAll() {
    return this.store.getAll();
  }

  setAll(settings) {
    this.store.setAll(settings);

    Object.keys(settings).forEach((key) => {
      this.emit(key, settings[key]);
    });
  }

}

export default SettingsManager;
<commit_msg>User lower step for volume<commit_after>import store2 from 'store2';
import EventEmitter from 'events';

const STORE_NAMESPACE = 'soundboard';

const DEFAULT_SETTINGS = {
  volume: 1.0,
  theme: 'default',
};

export const settingManifest = {
  volume: {
    label: 'Volume',
    type: 'slider',
    params: { min: 0, max: 100, step: 5, multiplier: 100 },
  },
  theme: {
    label: 'Theme',
    type: 'theme',
  },
};

class SettingsManager extends EventEmitter {

  /** @type SettingsManager */
  static instance;

  store;

  static init() {
    this.instance = new SettingsManager();
  }

  constructor() {
    super();

    // Init store with namespace
    this.store = store2.namespace(STORE_NAMESPACE);
    // Set default settings, without overwrite
    this.store.setAll(DEFAULT_SETTINGS, false);
  }

  set(key, value, overwrite = true) {
    this.store.set(key, value, overwrite);

    this.emit(key, value);
  }

  get(key) {
    return this.store.get(key);
  }

  getAll() {
    return this.store.getAll();
  }

  setAll(settings) {
    this.store.setAll(settings);

    Object.keys(settings).forEach((key) => {
      this.emit(key, settings[key]);
    });
  }

}

export default SettingsManager;
<|endoftext|>


<commit_before>// http://stackoverflow.com/a/12646864/92396
function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

links = $('#mw-content-text p a').not($('.reference a'))
words = new Set(links.toArray().map(link => link.text))
words = Array.from(new Set(words)); // keep only unique

if (links.length >= 4) { // if less – we don't have enough options to choose for dropdowns
	links.replaceWith(function() {
		var correct = $(this).text();
		var options = [correct];
		while (options.length < 4) {
			word = words[Math.floor(Math.random() * words.length)];
			if (!options.includes(word)) {
				options.push(word);
			}
		}
		options = shuffleArray(options);
		var select = '<select><option>' + options.join('</option><option>') + '</option></select>';
		var item = $(select)
		item.change(function(){
			val = $(this).val()
			if (val === correct) {
				$(this).css('background-color', 'lightgreen');
			}
			else {
				$(this).css('background-color', 'lightcoral');
			}
		});
		item.prop("selectedIndex", -1);
		return item;
	});
}
<commit_msg>Add switcher to the top of wiki pages<commit_after>function shuffleArray(array) {
	// http://stackoverflow.com/a/12646864/92396
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

function createQuizzes() {
	links = $('#mw-content-text p a').not($('.reference a'))
	words = new Set(links.toArray().map(link => link.text))
	words = Array.from(new Set(words)); // keep only unique

	if (links.length >= 4) { // if less – we don't have enough options to choose for dropdowns
		links.replaceWith(function() {
			var correct = $(this).text();
			var options = [correct];
			while (options.length < 4) {
				word = words[Math.floor(Math.random() * words.length)];
				if (!options.includes(word)) {
					options.push(word);
				}
			}
			options = shuffleArray(options);
			var select = '<select><option>' + options.join('</option><option>') + '</option></select>';
			var item = $(select)
			item.change(function(){
				val = $(this).val()
				if (val === correct) {
					$(this).css('background-color', 'lightgreen');
				}
				else {
					$(this).css('background-color', 'lightcoral');
				}
			});
			item.prop("selectedIndex", -1);
			return item;
		});
	}
}

// TODO: wait here for jQuery to load

switcher = $('<a>[TEST YOURSELF]</a>').click(createQuizzes).css('color', 'red');
$('#firstHeading').append(' ').append(switcher);
<|endoftext|>


<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({
processing: {
//prompt: (bot) => bot.say('...'),
receive: () => 'processing'
},

start: {
receive: (bot,message) => {
return bot.say(`${groet} - welkom bij Independer.`)
.then(() => 'askName');
}
},

bye: {
prompt: (bot) => bot.say('Geen probleem.'),
receive: () => 'processing'
},

/*
askName: {
prompt: (bot) => bot.say('Hoe heet je?'),
receive: (bot,message) => {
const name = message.text;
return bot.setProp('name', name)
.then(() => bot.say(`Ok ${name}, hoe kan ik je helpen? \n
%[Heb je schade](postback:schade) %[Zoek je een verzekering](postback:zoek)`))
.then(() => 'processing');
},
},
*/

askName: {
    prompt: (bot) => bot.say('Postback is working. What\'s your name?'),
    receive: (bot, message) => {
        const name = message.text;
        return bot.setProp('name', name)
            .then(() => bot.say(`Great! I\'ll call you ${name}`))
            .then(()=> bot.say('Is that OK? %[Yes](postback:yes) %[No](postback:nee)'))
            .then(() => 'speak');
    }
},

error: {
prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
receive: () => ''
},

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>we<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({
processing: {
//prompt: (bot) => bot.say('...'),
receive: () => 'processing'
},

start: {
receive: (bot,message) => {
  const name = message.text;
  return bot.setProp('name', name)
      .then(() => bot.say(`Great! I\'ll call you ${name}`))
.then(() =>  bot.say(`${groet} - welkom bij Independer.`))
.then(() => 'askName');
}
},

bye: {
prompt: (bot) => bot.say('Geen probleem.'),
receive: () => 'processing'
},

/*
askName: {
prompt: (bot) => bot.say('Hoe heet je?'),
receive: (bot,message) => {
const name = message.text;
return bot.setProp('name', name)
.then(() => bot.say(`Ok ${name}, hoe kan ik je helpen? \n
%[Heb je schade](postback:schade) %[Zoek je een verzekering](postback:zoek)`))
.then(() => 'processing');
},
},
*/

askName: {
    prompt: (bot) => bot.say('Postback is working. What\'s your name?'),
    receive: (bot, message) => {
        const name = message.text;
        return bot.setProp('name', name)
            .then(() => bot.say(`Great! I\'ll call you ${name}`))
            .then(()=> bot.say('Is that OK? %[Yes](postback:yes) %[No](postback:nee)'))
            .then(() => 'speak');
    }
},

error: {
prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
receive: () => ''
},

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>/**
 * TridentSelection.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://tinymce.moxiecode.com/license
 * Contributing: http://tinymce.moxiecode.com/contributing
 */

(function() {
	function Selection(selection) {
		var self = this, dom = selection.dom, TRUE = true, FALSE = false;

		function getPosition(rng, start) {
			var checkRng, startIndex = 0, endIndex, inside,
				children, child, offset, index, position = -1, parent;

			// Setup test range, collapse it and get the parent
			checkRng = rng.duplicate();
			checkRng.collapse(start);
			parent = checkRng.parentElement();

			// Check if the selection is within the right document
			if (parent.ownerDocument !== selection.dom.doc)
				return;

			// IE will report non editable elements as it's parent so look for an editable one
			while (parent.contentEditable === "false") {
				parent = parent.parentNode;
			}

			// If parent doesn't have any children then return that we are inside the element
			if (!parent.hasChildNodes()) {
				return {node : parent, inside : 1};
			}

			// Setup node list and endIndex
			children = parent.children;
			endIndex = children.length - 1;

			// Perform a binary search for the position
			while (startIndex <= endIndex) {
				index = Math.floor((startIndex + endIndex) / 2);

				// Move selection to node and compare the ranges
				child = children[index];
				checkRng.moveToElementText(child);
				position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng);

				// Before/after or an exact match
				if (position > 0) {
					endIndex = index - 1;
				} else if (position < 0) {
					startIndex = index + 1;
				} else {
					return {node : child};
				}
			}

			// Check if child position is before or we didn't find a position
			if (position < 0) {
				// No element child was found use the parent element and the offset inside that
				if (!child) {
					checkRng.moveToElementText(parent);
					checkRng.collapse(true);
					child = parent;
					inside = true;
				} else
					checkRng.collapse(false);

				checkRng.setEndPoint(start ? 'EndToStart' : 'EndToEnd', rng);

				// Fix for edge case:

..
ab|c

				if (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) > 0) {
					checkRng = rng.duplicate();
					checkRng.collapse(start);

					offset = -1;
					while (parent == checkRng.parentElement()) {
						if (checkRng.move('character', -1) == 0)
							break;

						offset++;
					}
				}

				offset = offset || checkRng.text.replace('\r\n', ' ').length;
			} else {
				// Child position is after the selection endpoint
				checkRng.collapse(true);
				checkRng.setEndPoint(start ? 'StartToStart' : 'StartToEnd', rng);

				// Get the length of the text to find where the endpoint is relative to it's container
				offset = checkRng.text.replace('\r\n', ' ').length;
			}

			return {node : child, position : position, offset : offset, inside : inside};
		};

		// Returns a W3C DOM compatible range object by using the IE Range API
		function getRange() {
			var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail;

			// If selection is outside the current document just return an empty range
			element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
			if (element.ownerDocument != dom.doc)
				return domRange;

			collapsed = selection.isCollapsed();

			// Handle control selection
			if (ieRange.item) {
				domRange.setStart(element.parentNode, dom.nodeIndex(element));
				domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);

				return domRange;
			}

			function findEndPoint(start) {
				var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue;

				container = endPoint.node;
				offset = endPoint.offset;

				if (endPoint.inside && !container.hasChildNodes()) {
					domRange[start ? 'setStart' : 'setEnd'](container, 0);
					return;
				}

				if (offset === undef) {
					domRange[start ? 'setStartBefore' : 'setEndAfter'](container);
					return;
				}

				if (endPoint.position < 0) {
					sibling = endPoint.inside ? container.firstChild : container.nextSibling;

					if (!sibling) {
						domRange[start ? 'setStartAfter' : 'setEndAfter'](container);
						return;
					}

					if (!offset) {
						if (sibling.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, 0);
						else
							domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling);

						return;
					}

					// Find the text node and offset
					while (sibling) {
						nodeValue = sibling.nodeValue;
						textNodeOffset += nodeValue.length;

						// We are at or passed the position we where looking for
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							textNodeOffset = nodeValue.length - textNodeOffset;
							break;
						}

						sibling = sibling.nextSibling;
					}
				} else {
					// Find the text node and offset
					sibling = container.previousSibling;

					if (!sibling)
						return domRange[start ? 'setStartBefore' : 'setEndBefore'](container);

					// If there isn't any text to loop then use the first position
					if (!offset) {
						if (container.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length);
						else
							domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling);

						return;
					}

					while (sibling) {
						textNodeOffset += sibling.nodeValue.length;

						// We are at or passed the position we where looking for
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							break;
						}

						sibling = sibling.previousSibling;
					}
				}

				domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset);
			};

			try {
				// Find start point
				findEndPoint(true);

				// Find end point if needed
				if (!collapsed)
					findEndPoint();
			} catch (ex) {
				// IE has a nasty bug where text nodes might throw "invalid argument" when you
				// access the nodeValue or other properties of text nodes. This seems to happend when
				// text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it.
				if (ex.number == -2147024809) {
					// Get the current selection
					bookmark = self.getBookmark(2);

					// Get start element
					tmpRange = ieRange.duplicate();
					tmpRange.collapse(true);
					element = tmpRange.parentElement();

					// Get end element
					if (!collapsed) {
						tmpRange = ieRange.duplicate();
						tmpRange.collapse(false);
						element2 = tmpRange.parentElement();
						element2.innerHTML = element2.innerHTML;
					}

					// Remove the broken elements
					element.innerHTML = element.innerHTML;

					// Restore the selection
					self.moveToBookmark(bookmark);

					// Since the range has moved we need to re-get it
					ieRange = selection.getRng();

					// Find start point
					findEndPoint(true);

					// Find end point if needed
					if (!collapsed)
						findEndPoint();
				} else
					throw ex; // Throw other errors
			}

			return domRange;
		};

		this.getBookmark = function(type) {
			var rng = selection.getRng(), start, end, bookmark = {};

			function getIndexes(node) {
				var node, parent, root, children, i, indexes = [];

				parent = node.parentNode;
				root = dom.getRoot().parentNode;

				while (parent != root && parent.nodeType !== 9) {
					children = parent.children;

					i = children.length;
					while (i--) {
						if (node === children[i]) {
							indexes.push(i);
							break;
						}
					}

					node = parent;
					parent = parent.parentNode;
				}

				return indexes;
			};

			function getBookmarkEndPoint(start) {
				var position;

				position = getPosition(rng, start);
				if (position) {
					return {
						position : position.position,
						offset : position.offset,
						indexes : getIndexes(position.node),
						inside : position.inside
					};
				}
			};

			// Non ubstructive bookmark
			if (type === 2) {
				// Handle text selection
				if (!rng.item) {
					bookmark.start = getBookmarkEndPoint(true);

					if (!selection.isCollapsed())
						bookmark.end = getBookmarkEndPoint();
				} else
					bookmark.start = {ctrl : true, indexes : getIndexes(rng.item(0))};
			}

			return bookmark;
		};

		this.moveToBookmark = function(bookmark) {
			var rng, body = dom.doc.body;

			function resolveIndexes(indexes) {
				var node, i, idx, children;

				node = dom.getRoot();
				for (i = indexes.length - 1; i >= 0; i--) {
					children = node.children;
					idx = indexes[i];

					if (idx <= children.length - 1) {
						node = children[idx];
					}
				}

				return node;
			};

			function setBookmarkEndPoint(start) {
				var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef;

				if (endPoint) {
					moveLeft = endPoint.position > 0;

					moveRng = body.createTextRange();
					moveRng.moveToElementText(resolveIndexes(endPoint.indexes));

					offset = endPoint.offset;
					if (offset !== undef) {
						moveRng.collapse(endPoint.inside || moveLeft);
						moveRng.moveStart('character', moveLeft ? -offset : offset);
					} else
						moveRng.collapse(start);

					rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng);

					if (start)
						rng.collapse(true);
				}
			};

			if (bookmark.start) {
				if (bookmark.start.ctrl) {
					rng = body.createControlRange();
					rng.addElement(resolveIndexes(bookmark.start.indexes));
					rng.select();
				} else {
					rng = body.createTextRange();
					setBookmarkEndPoint(true);
					setBookmarkEndPoint();
					rng.select();
				}
			}
		};

		this.addRange = function(rng) {
			var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body;

			function setEndPoint(start) {
				var container, offset, marker, tmpRng, nodes;

				marker = dom.create('a');
				container = start ? startContainer : endContainer;
				offset = start ? startOffset : endOffset;
				tmpRng = ieRng.duplicate();

				if (container == doc || container == doc.documentElement) {
					container = body;
					offset = 0;
				}

				if (container.nodeType == 3) {
					container.parentNode.insertBefore(marker, container);
					tmpRng.moveToElementText(marker);
					tmpRng.moveStart('character', offset);
					dom.remove(marker);
					ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
				} else {
					nodes = container.childNodes;

					if (nodes.length) {
						if (offset >= nodes.length) {
							dom.insertAfter(marker, nodes[nodes.length - 1]);
						} else {
							container.insertBefore(marker, nodes[offset]);
						}

						tmpRng.moveToElementText(marker);
					} else if (container.canHaveHTML) {
						// Empty node selection for example
|

						marker = doc.createTextNode('\uFEFF');
						container.appendChild(marker);
						tmpRng.moveToElementText(marker.parentNode);
						tmpRng.collapse(TRUE);
						//tmpRng.select();
					}

					ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
					dom.remove(marker);
				}
			}

			// Setup some shorter versions
			startContainer = rng.startContainer;
			startOffset = rng.startOffset;
			endContainer = rng.endContainer;
			endOffset = rng.endOffset;
			ieRng = body.createTextRange();

			// If single element selection then try making a control selection out of it
			if (startContainer == endContainer && startContainer.nodeType == 1 && startOffset == endOffset - 1) {
				if (startOffset == endOffset - 1) {
					try {
						ctrlRng = body.createControlRange();
						ctrlRng.addElement(startContainer.childNodes[startOffset]);
						ctrlRng.select();
						return;
					} catch (ex) {
						// Ignore
					}
				}
			}

			// Set start/end point of selection
			setEndPoint(true);
			setEndPoint();

			// Select the new range and scroll it into view
			ieRng.select();
		};

		// Expose range method
		this.getRangeAt = getRange;
	};

	// Expose the selection object
	tinymce.dom.TridentSelection = Selection;
})();
<commit_msg>Fixed bug where selecting empty block elements didn't render the block on IE.<commit_after>/**
 * TridentSelection.js
 *
 * Copyright 2009, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://tinymce.moxiecode.com/license
 * Contributing: http://tinymce.moxiecode.com/contributing
 */

(function() {
	function Selection(selection) {
		var self = this, dom = selection.dom, TRUE = true, FALSE = false;

		function getPosition(rng, start) {
			var checkRng, startIndex = 0, endIndex, inside,
				children, child, offset, index, position = -1, parent;

			// Setup test range, collapse it and get the parent
			checkRng = rng.duplicate();
			checkRng.collapse(start);
			parent = checkRng.parentElement();

			// Check if the selection is within the right document
			if (parent.ownerDocument !== selection.dom.doc)
				return;

			// IE will report non editable elements as it's parent so look for an editable one
			while (parent.contentEditable === "false") {
				parent = parent.parentNode;
			}

			// If parent doesn't have any children then return that we are inside the element
			if (!parent.hasChildNodes()) {
				return {node : parent, inside : 1};
			}

			// Setup node list and endIndex
			children = parent.children;
			endIndex = children.length - 1;

			// Perform a binary search for the position
			while (startIndex <= endIndex) {
				index = Math.floor((startIndex + endIndex) / 2);

				// Move selection to node and compare the ranges
				child = children[index];
				checkRng.moveToElementText(child);
				position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng);

				// Before/after or an exact match
				if (position > 0) {
					endIndex = index - 1;
				} else if (position < 0) {
					startIndex = index + 1;
				} else {
					return {node : child};
				}
			}

			// Check if child position is before or we didn't find a position
			if (position < 0) {
				// No element child was found use the parent element and the offset inside that
				if (!child) {
					checkRng.moveToElementText(parent);
					checkRng.collapse(true);
					child = parent;
					inside = true;
				} else
					checkRng.collapse(false);

				checkRng.setEndPoint(start ? 'EndToStart' : 'EndToEnd', rng);

				// Fix for edge case:

..
ab|c

				if (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) > 0) {
					checkRng = rng.duplicate();
					checkRng.collapse(start);

					offset = -1;
					while (parent == checkRng.parentElement()) {
						if (checkRng.move('character', -1) == 0)
							break;

						offset++;
					}
				}

				offset = offset || checkRng.text.replace('\r\n', ' ').length;
			} else {
				// Child position is after the selection endpoint
				checkRng.collapse(true);
				checkRng.setEndPoint(start ? 'StartToStart' : 'StartToEnd', rng);

				// Get the length of the text to find where the endpoint is relative to it's container
				offset = checkRng.text.replace('\r\n', ' ').length;
			}

			return {node : child, position : position, offset : offset, inside : inside};
		};

		// Returns a W3C DOM compatible range object by using the IE Range API
		function getRange() {
			var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail;

			// If selection is outside the current document just return an empty range
			element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
			if (element.ownerDocument != dom.doc)
				return domRange;

			collapsed = selection.isCollapsed();

			// Handle control selection
			if (ieRange.item) {
				domRange.setStart(element.parentNode, dom.nodeIndex(element));
				domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);

				return domRange;
			}

			function findEndPoint(start) {
				var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue;

				container = endPoint.node;
				offset = endPoint.offset;

				if (endPoint.inside && !container.hasChildNodes()) {
					domRange[start ? 'setStart' : 'setEnd'](container, 0);
					return;
				}

				if (offset === undef) {
					domRange[start ? 'setStartBefore' : 'setEndAfter'](container);
					return;
				}

				if (endPoint.position < 0) {
					sibling = endPoint.inside ? container.firstChild : container.nextSibling;

					if (!sibling) {
						domRange[start ? 'setStartAfter' : 'setEndAfter'](container);
						return;
					}

					if (!offset) {
						if (sibling.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, 0);
						else
							domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling);

						return;
					}

					// Find the text node and offset
					while (sibling) {
						nodeValue = sibling.nodeValue;
						textNodeOffset += nodeValue.length;

						// We are at or passed the position we where looking for
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							textNodeOffset = nodeValue.length - textNodeOffset;
							break;
						}

						sibling = sibling.nextSibling;
					}
				} else {
					// Find the text node and offset
					sibling = container.previousSibling;

					if (!sibling)
						return domRange[start ? 'setStartBefore' : 'setEndBefore'](container);

					// If there isn't any text to loop then use the first position
					if (!offset) {
						if (container.nodeType == 3)
							domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length);
						else
							domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling);

						return;
					}

					while (sibling) {
						textNodeOffset += sibling.nodeValue.length;

						// We are at or passed the position we where looking for
						if (textNodeOffset >= offset) {
							container = sibling;
							textNodeOffset -= offset;
							break;
						}

						sibling = sibling.previousSibling;
					}
				}

				domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset);
			};

			try {
				// Find start point
				findEndPoint(true);

				// Find end point if needed
				if (!collapsed)
					findEndPoint();
			} catch (ex) {
				// IE has a nasty bug where text nodes might throw "invalid argument" when you
				// access the nodeValue or other properties of text nodes. This seems to happend when
				// text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it.
				if (ex.number == -2147024809) {
					// Get the current selection
					bookmark = self.getBookmark(2);

					// Get start element
					tmpRange = ieRange.duplicate();
					tmpRange.collapse(true);
					element = tmpRange.parentElement();

					// Get end element
					if (!collapsed) {
						tmpRange = ieRange.duplicate();
						tmpRange.collapse(false);
						element2 = tmpRange.parentElement();
						element2.innerHTML = element2.innerHTML;
					}

					// Remove the broken elements
					element.innerHTML = element.innerHTML;

					// Restore the selection
					self.moveToBookmark(bookmark);

					// Since the range has moved we need to re-get it
					ieRange = selection.getRng();

					// Find start point
					findEndPoint(true);

					// Find end point if needed
					if (!collapsed)
						findEndPoint();
				} else
					throw ex; // Throw other errors
			}

			return domRange;
		};

		this.getBookmark = function(type) {
			var rng = selection.getRng(), start, end, bookmark = {};

			function getIndexes(node) {
				var node, parent, root, children, i, indexes = [];

				parent = node.parentNode;
				root = dom.getRoot().parentNode;

				while (parent != root && parent.nodeType !== 9) {
					children = parent.children;

					i = children.length;
					while (i--) {
						if (node === children[i]) {
							indexes.push(i);
							break;
						}
					}

					node = parent;
					parent = parent.parentNode;
				}

				return indexes;
			};

			function getBookmarkEndPoint(start) {
				var position;

				position = getPosition(rng, start);
				if (position) {
					return {
						position : position.position,
						offset : position.offset,
						indexes : getIndexes(position.node),
						inside : position.inside
					};
				}
			};

			// Non ubstructive bookmark
			if (type === 2) {
				// Handle text selection
				if (!rng.item) {
					bookmark.start = getBookmarkEndPoint(true);

					if (!selection.isCollapsed())
						bookmark.end = getBookmarkEndPoint();
				} else
					bookmark.start = {ctrl : true, indexes : getIndexes(rng.item(0))};
			}

			return bookmark;
		};

		this.moveToBookmark = function(bookmark) {
			var rng, body = dom.doc.body;

			function resolveIndexes(indexes) {
				var node, i, idx, children;

				node = dom.getRoot();
				for (i = indexes.length - 1; i >= 0; i--) {
					children = node.children;
					idx = indexes[i];

					if (idx <= children.length - 1) {
						node = children[idx];
					}
				}

				return node;
			};

			function setBookmarkEndPoint(start) {
				var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef;

				if (endPoint) {
					moveLeft = endPoint.position > 0;

					moveRng = body.createTextRange();
					moveRng.moveToElementText(resolveIndexes(endPoint.indexes));

					offset = endPoint.offset;
					if (offset !== undef) {
						moveRng.collapse(endPoint.inside || moveLeft);
						moveRng.moveStart('character', moveLeft ? -offset : offset);
					} else
						moveRng.collapse(start);

					rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng);

					if (start)
						rng.collapse(true);
				}
			};

			if (bookmark.start) {
				if (bookmark.start.ctrl) {
					rng = body.createControlRange();
					rng.addElement(resolveIndexes(bookmark.start.indexes));
					rng.select();
				} else {
					rng = body.createTextRange();
					setBookmarkEndPoint(true);
					setBookmarkEndPoint();
					rng.select();
				}
			}
		};

		this.addRange = function(rng) {
			var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body;

			function setEndPoint(start) {
				var container, offset, marker, tmpRng, nodes;

				marker = dom.create('a');
				container = start ? startContainer : endContainer;
				offset = start ? startOffset : endOffset;
				tmpRng = ieRng.duplicate();

				if (container == doc || container == doc.documentElement) {
					container = body;
					offset = 0;
				}

				if (container.nodeType == 3) {
					container.parentNode.insertBefore(marker, container);
					tmpRng.moveToElementText(marker);
					tmpRng.moveStart('character', offset);
					dom.remove(marker);
					ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
				} else {
					nodes = container.childNodes;

					if (nodes.length) {
						if (offset >= nodes.length) {
							dom.insertAfter(marker, nodes[nodes.length - 1]);
						} else {
							container.insertBefore(marker, nodes[offset]);
						}

						tmpRng.moveToElementText(marker);
					} else if (container.canHaveHTML) {
						// Empty node selection for example
|

						// Setting innerHTML with a span marker then remove that marker seems to keep empty block elements open
						container.innerHTML = '\uFEFF';
						marker = container.firstChild;
						tmpRng.moveToElementText(marker);
						tmpRng.collapse(FALSE); // Collapse false works better than true for some odd reason
					}

					ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng);
					dom.remove(marker);
				}
			}

			// Setup some shorter versions
			startContainer = rng.startContainer;
			startOffset = rng.startOffset;
			endContainer = rng.endContainer;
			endOffset = rng.endOffset;
			ieRng = body.createTextRange();

			// If single element selection then try making a control selection out of it
			if (startContainer == endContainer && startContainer.nodeType == 1 && startOffset == endOffset - 1) {
				if (startOffset == endOffset - 1) {
					try {
						ctrlRng = body.createControlRange();
						ctrlRng.addElement(startContainer.childNodes[startOffset]);
						ctrlRng.select();
						return;
					} catch (ex) {
						// Ignore
					}
				}
			}

			// Set start/end point of selection
			setEndPoint(true);
			setEndPoint();

			// Select the new range and scroll it into view
			ieRng.select();
		};

		// Expose range method
		this.getRangeAt = getRange;
	};

	// Expose the selection object
	tinymce.dom.TridentSelection = Selection;
})();
<|endoftext|>


<commit_before>// Copyright 2002-2013, University of Colorado Boulder

/**
 * When a level is completed, this node shows how you did.
 *
 * @author John Blanco
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // Imports
  var Color = require( 'SCENERY/util/Color' );
  var ProgressIndicator = require( 'VEGAS/ProgressIndicator' );
  var GameTimer = require( 'VEGAS/GameTimer' );
  var inherit = require( 'PHET_CORE/inherit' );
  var MultiLineText = require( 'SCENERY_PHET/MultiLineText' );
  var Panel = require( 'SUN/Panel' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var StringUtils = require( 'PHETCOMMON/util/StringUtils' );
  var Text = require( 'SCENERY/nodes/Text' );
  var TextPushButtonDeprecated = require( 'SUN/TextPushButtonDeprecated' );
  var VBox = require( 'SCENERY/nodes/VBox' );

  // Strings
  var keepTryingString = require( 'string!VEGAS/keepTrying' );
  var goodString = require( 'string!VEGAS/good' );
  var greatString = require( 'string!VEGAS/great' );
  var excellentString = require( 'string!VEGAS/excellent' );
  var scoreOutOfString = require( 'string!VEGAS/label.score.max' );
  var timeString = require( 'string!VEGAS/label.time' );
  var yourNewBestString = require( 'string!VEGAS/yourNewBest' );
  var pattern0YourBestString = require( 'string!VEGAS/pattern.0yourBest' );
  var continueString = require( 'string!VEGAS/continue' );
  var levelString = require( 'string!VEGAS/label.level' );

  /**
   * @param {number} level starting from zero, 1 added to this when displayed
   * @param {number} score
   * @param {number} perfectScore
   * @param {number} numStars
   * @param {boolean} timerEnabled
   * @param {number} elapsedTime (in seconds)
   * @param {number} bestTimeAtThisLevel (in seconds), null indicates no best time
   * @param {boolean} isNewBestTime
   * @param {function} continueFunction Function to call when the user presses the 'Continue' button.
   * @param {*} options
   * @constructor
   */
  function LevelCompletedNode( level, score, perfectScore, numStars, timerEnabled, elapsedTime, bestTimeAtThisLevel, isNewBestTime, continueFunction, options ) {

    options = _.extend( {
      levelVisible: true, // display the level number?
      fill: new Color( 180, 205, 255 ),
      stroke: 'black',
      lineWidth: 2,
      cornerRadius: 35,
      xMargin: 20,
      yMargin: 20,
      ySpacing: 30,
      titleFont: new PhetFont( { size: 28, weight: 'bold' } ),
      infoFont: new PhetFont( { size: 22, weight: 'bold' } ),
      buttonFont: new PhetFont( 26 ),
      buttonFill: new Color( 255, 255, 0 ),
      starDiameter: 62
    }, options );

    // nodes to be added to the panel
    var children = [];

    // Title, which changes based on how the user did.
    var proportionCorrect = score / perfectScore;
    var titleText = keepTryingString;
    if ( proportionCorrect > 0.95 ) {
      titleText = excellentString;
    }
    else if ( proportionCorrect > 0.75 ) {
      titleText = greatString;
    }
    else if ( proportionCorrect >= 0.5 ) {
      titleText = goodString;
    }
    var title = new Text( titleText, {font: options.titleFont} );
    children.push( title );

    // Progress indicator
    children.push( new ProgressIndicator( numStars, options.starDiameter, new Property( score ), perfectScore ) ); //TODO propagate options related to ProgressIndicator

    // Level (optional)
    if ( options.levelVisible ) {
      children.push( new Text( StringUtils.format( levelString, level + 1 ), { font: options.infoFont } ) );
    }

    // Score
    children.push( new Text( StringUtils.format( scoreOutOfString, score, perfectScore ), { font: options.infoFont } ) );

    // Time (optional)
    if ( timerEnabled ) {
      var time = new MultiLineText( StringUtils.format( timeString, GameTimer.formatTime( elapsedTime ) ), { font: options.infoFont, align: 'center' } );
      if ( isNewBestTime ) {
        time.text += '\n' + yourNewBestString;
      }
      else if ( bestTimeAtThisLevel !== null ) {
        time.text += '\n' + StringUtils.format( pattern0YourBestString, GameTimer.formatTime( bestTimeAtThisLevel ) );
      }
      children.push( time );
    }

    // Continue button
    children.push( new TextPushButtonDeprecated( continueString, {
      listener: continueFunction,
      font: options.buttonFont,
      rectangleFillUp: options.buttonFill,
      rectangleXMargin: 10,
      rectangleYMargin: 5
    } ) );

    // Panel
    Panel.call( this, new VBox( { children: children, spacing: options.ySpacing } ), options );
  }

  // Inherit from Node.
  return inherit( Panel, LevelCompletedNode );
} );
<commit_msg>Modified LevelCompletedNode to use the new button style, see https://github.com/phetsims/sun/issues/94.<commit_after>// Copyright 2002-2013, University of Colorado Boulder

/**
 * When a level is completed, this node shows how you did.
 *
 * @author John Blanco
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // Imports
  var Color = require( 'SCENERY/util/Color' );
  var ProgressIndicator = require( 'VEGAS/ProgressIndicator' );
  var GameTimer = require( 'VEGAS/GameTimer' );
  var inherit = require( 'PHET_CORE/inherit' );
  var MultiLineText = require( 'SCENERY_PHET/MultiLineText' );
  var Panel = require( 'SUN/Panel' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var StringUtils = require( 'PHETCOMMON/util/StringUtils' );
  var Text = require( 'SCENERY/nodes/Text' );
  var TextPushButton = require( 'SUN/buttons/TextPushButton' );
  var VBox = require( 'SCENERY/nodes/VBox' );

  // Strings
  var keepTryingString = require( 'string!VEGAS/keepTrying' );
  var goodString = require( 'string!VEGAS/good' );
  var greatString = require( 'string!VEGAS/great' );
  var excellentString = require( 'string!VEGAS/excellent' );
  var scoreOutOfString = require( 'string!VEGAS/label.score.max' );
  var timeString = require( 'string!VEGAS/label.time' );
  var yourNewBestString = require( 'string!VEGAS/yourNewBest' );
  var pattern0YourBestString = require( 'string!VEGAS/pattern.0yourBest' );
  var continueString = require( 'string!VEGAS/continue' );
  var levelString = require( 'string!VEGAS/label.level' );

  /**
   * @param {number} level starting from zero, 1 added to this when displayed
   * @param {number} score
   * @param {number} perfectScore
   * @param {number} numStars
   * @param {boolean} timerEnabled
   * @param {number} elapsedTime (in seconds)
   * @param {number} bestTimeAtThisLevel (in seconds), null indicates no best time
   * @param {boolean} isNewBestTime
   * @param {function} continueFunction Function to call when the user presses the 'Continue' button.
   * @param {*} options
   * @constructor
   */
  function LevelCompletedNode( level, score, perfectScore, numStars, timerEnabled, elapsedTime, bestTimeAtThisLevel, isNewBestTime, continueFunction, options ) {

    options = _.extend( {
      levelVisible: true, // display the level number?
      fill: new Color( 180, 205, 255 ),
      stroke: 'black',
      lineWidth: 2,
      cornerRadius: 35,
      xMargin: 20,
      yMargin: 20,
      ySpacing: 30,
      titleFont: new PhetFont( { size: 28, weight: 'bold' } ),
      infoFont: new PhetFont( { size: 22, weight: 'bold' } ),
      buttonFont: new PhetFont( 26 ),
      buttonFill: new Color( 255, 255, 0 ),
      starDiameter: 62
    }, options );

    // nodes to be added to the panel
    var children = [];

    // Title, which changes based on how the user did.
    var proportionCorrect = score / perfectScore;
    var titleText = keepTryingString;
    if ( proportionCorrect > 0.95 ) {
      titleText = excellentString;
    }
    else if ( proportionCorrect > 0.75 ) {
      titleText = greatString;
    }
    else if ( proportionCorrect >= 0.5 ) {
      titleText = goodString;
    }
    var title = new Text( titleText, {font: options.titleFont} );
    children.push( title );

    // Progress indicator
    children.push( new ProgressIndicator( numStars, options.starDiameter, new Property( score ), perfectScore ) ); //TODO propagate options related to ProgressIndicator

    // Level (optional)
    if ( options.levelVisible ) {
      children.push( new Text( StringUtils.format( levelString, level + 1 ), { font: options.infoFont } ) );
    }

    // Score
    children.push( new Text( StringUtils.format( scoreOutOfString, score, perfectScore ), { font: options.infoFont } ) );

    // Time (optional)
    if ( timerEnabled ) {
      var time = new MultiLineText( StringUtils.format( timeString, GameTimer.formatTime( elapsedTime ) ), { font: options.infoFont, align: 'center' } );
      if ( isNewBestTime ) {
        time.text += '\n' + yourNewBestString;
      }
      else if ( bestTimeAtThisLevel !== null ) {
        time.text += '\n' + StringUtils.format( pattern0YourBestString, GameTimer.formatTime( bestTimeAtThisLevel ) );
      }
      children.push( time );
    }

    // Continue button
    children.push( new TextPushButton( continueString, {
      listener: continueFunction,
      font: options.buttonFont,
      baseColor: options.buttonFill,
      rectangleXMargin: 10,
      rectangleYMargin: 5
    } ) );

    // Panel
    Panel.call( this, new VBox( { children: children, spacing: options.ySpacing } ), options );
  }

  // Inherit from Node.
  return inherit( Panel, LevelCompletedNode );
} );
<|endoftext|>


<commit_before>module.exports = {
  /**
   * Extract YNAB data from the selection and put it on a CSV string.
   * @param  {DomSelectionRange} domSelectionRange - selection range.
   * @return {string} CSV string with YNAB data.
   * @throws {Error} If no YNAB data was found in the selection.
   */
  generateCsv: (domSelectionRange) => {
    //TODO
  }
}
<commit_msg>YNAB exporter blueprint<commit_after>import tabular from "./utils/tabular-data"
import columnFinder from "./ynab/column-finder"
import transactionFactory from "./ynab/transaction-factory"
import csvBuilder from "./ynab/csv-builder"

module.exports = {
  /**
   * Extract YNAB data from the selection and put it on a CSV string.
   * @param  {DomSelectionRange} domSelectionRange - selection range.
   * @return {string} CSV string with YNAB data.
   * @throws {Error} If no YNAB data was found in the selection.
   */
  generateCsv: (domSelectionRange) => {
    var tabularData = tabular.getTabularDataFromSelection(domSelectionRange)

    var columnInfo = columnFinder.getColumnInfo(tabularData)

    var transactions = transactionFactory.createTransactions(tabularData, columnInfo)

    //ynabPostExtractProcessing.processInplace(ynabTxs)

    var csv = csvBuilder.buildCsv(transactions)

    return csv
  }
}
<|endoftext|>