<commit_before>module.exports = {
  components: {
    'overview-nav': require('./nav'),
    'overview-footer': require('./footer'),
    'error': require('../notification')
  },

  data: function() {
    return {
      store: window.Store.shareList,
      uiState: {
        selected: []
      }
    }
  },

  computed: {
    listHasItems: function() {
      return this.uiState.selected.length > 0;
    }
  },

  created: function() {
    this.store.actions.status(() => {
      this.store.actions.poll().start();
    });

  },

  destroyed: function() {
    this.store.actions.poll().stop();
  },

  methods: {
    toggleAll: function() {
      if(this.listHasItems) {
        this.uiState.selected = [];
      } else {
        this.store.shares.forEach((share) => {
          this.uiState.selected.push(share.id);
        });
      }
    },
    toggleItem: function(id) {
      let index = this.uiState.selected.indexOf(id);
      if(index >= 0) {
        this.uiState.selected.splice(index, 1);
      } else {
        this.uiState.selected.push(id);
      }
    }
  },

  template: `
<transition name="fade">

    <error class="error-stream alert alert-danger alert-dismissible" v-bind:notes="store.errors" v-bind:dismiss-action="store.actions.clearErrors"></error>

    <overview-nav></overview-nav>

Overview

                <input type="checkbox" v-model="listHasItems" v-on:change="toggleAll()" class="checkbox" id="selectAll">
                #
                Status

                Uptime
                Restarts
                Peers
                Shared

                    Start
                    Stop
                    Restart

                    Delete

                  <input v-model="uiState.selected"
                    v-on:change="toggleItem(share.id)"
                    v-bind:value="share.id"
                    type="checkbox"
                    class="checkbox">

                {{share.id}}

                {{share.meta.uptimeReadable}}
                {{share.meta.numRestarts}}
                {{share.meta.farmerState.totalPeers}}
                {{share.meta.farmerState.spaceUsed}} ({{share.meta.farmerState.percentUsed}}) %)

                    Start
                    Stop
                    Restart
                    Logs
                    Edit

                    Delete

                <router-link :to="{path: '/share-wizard/wizard1?edit=true'}">Add Drive to Get Started</router-link>

    <overview-footer></overview-footer>

</transition>
  `
};
<commit_msg>removing extra display character in overview template<commit_after>module.exports = {
  components: {
    'overview-nav': require('./nav'),
    'overview-footer': require('./footer'),
    'error': require('../notification')
  },

  data: function() {
    return {
      store: window.Store.shareList,
      uiState: {
        selected: []
      }
    }
  },

  computed: {
    listHasItems: function() {
      return this.uiState.selected.length > 0;
    }
  },

  created: function() {
    this.store.actions.status(() => {
      this.store.actions.poll().start();
    });

  },

  destroyed: function() {
    this.store.actions.poll().stop();
  },

  methods: {
    toggleAll: function() {
      if(this.listHasItems) {
        this.uiState.selected = [];
      } else {
        this.store.shares.forEach((share) => {
          this.uiState.selected.push(share.id);
        });
      }
    },
    toggleItem: function(id) {
      let index = this.uiState.selected.indexOf(id);
      if(index >= 0) {
        this.uiState.selected.splice(index, 1);
      } else {
        this.uiState.selected.push(id);
      }
    }
  },

  template: `
<transition name="fade">

    <error class="error-stream alert alert-danger alert-dismissible" v-bind:notes="store.errors" v-bind:dismiss-action="store.actions.clearErrors"></error>

    <overview-nav></overview-nav>

Overview

                <input type="checkbox" v-model="listHasItems" v-on:change="toggleAll()" class="checkbox" id="selectAll">
                #
                Status

                Uptime
                Restarts
                Peers
                Shared

                    Start
                    Stop
                    Restart

                    Delete

                  <input v-model="uiState.selected"
                    v-on:change="toggleItem(share.id)"
                    v-bind:value="share.id"
                    type="checkbox"
                    class="checkbox">

                {{share.id}}

                {{share.meta.uptimeReadable}}
                {{share.meta.numRestarts}}
                {{share.meta.farmerState.totalPeers}}
                {{share.meta.farmerState.spaceUsed}} ({{share.meta.farmerState.percentUsed}} %)

                    Start
                    Stop
                    Restart
                    Logs
                    Edit

                    Delete

                <router-link :to="{path: '/share-wizard/wizard1?edit=true'}">Add Drive to Get Started</router-link>

    <overview-footer></overview-footer>

</transition>
  `
};
<|endoftext|>


<commit_before>/**
UltimarteZoom - jQuery plugin for zooming images on web page.
@author Vladimir Kalmykov (http://github. )
*/
(function(jQuery) {
	var jQuery = jQuery;
	jQuery.tie = jQuery.fn.tie = function(func) {
		func.apply(this);
		return this;
	};

	jQuery.under = jQuery.fn.under = function(obj) {
		return jQuery(obj).prependTo(this);
	};

	jQuery.put = jQuery.fn.put = function(obj) {
		return jQuery(obj).appendTo(this);
	};

	jQuery.and = jQuery.fn.and = function(obj) {
		return jQuery(obj).insertAfter(this);
	};

	jQuery.condition = jQuery.fn.condition = function(condit, onTrue, onFalse) {
		if (condit) {
			if (typeof onTrue == 'function') return onTrue.call(this, condit);
			return this;
		} else {
			if (typeof onFalse == 'function') return onFalse.call(this);
			return this;
		};
	};

	jQuery.ramp = jQuery.fn.ramp = function() {
		var current = this;
		for (var i=0;i<arguments.length;i++) {
			var variable = arguments[i];
			if (variable instanceof Array) {
				for (var a=0;a<variable.length;a++) {
					jQuery(current).put(variable[variable]);
				};
				current = jQuery(current).parent();
			} else {
				current = jQuery(current).put(arguments[i])
			};
		};
		return current;
	};
})(jQuery)<commit_msg>fix title text<commit_after>/**
@author Vladimir Kalmykov (http://github. )
*/
(function(jQuery) {
	var jQuery = jQuery;
	jQuery.tie = jQuery.fn.tie = function(func) {
		func.apply(this);
		return this;
	};

	jQuery.under = jQuery.fn.under = function(obj) {
		return jQuery(obj).prependTo(this);
	};

	jQuery.put = jQuery.fn.put = function(obj) {
		return jQuery(obj).appendTo(this);
	};

	jQuery.and = jQuery.fn.and = function(obj) {
		return jQuery(obj).insertAfter(this);
	};

	jQuery.condition = jQuery.fn.condition = function(condit, onTrue, onFalse) {
		if (condit) {
			if (typeof onTrue == 'function') return onTrue.call(this, condit);
			return this;
		} else {
			if (typeof onFalse == 'function') return onFalse.call(this);
			return this;
		};
	};

	jQuery.ramp = jQuery.fn.ramp = function() {
		var current = this;
		for (var i=0;i<arguments.length;i++) {
			var variable = arguments[i];
			if (variable instanceof Array) {
				for (var a=0;a<variable.length;a++) {
					jQuery(current).put(variable[variable]);
				};
				current = jQuery(current).parent();
			} else {
				current = jQuery(current).put(arguments[i])
			};
		};
		return current;
	};
})(jQuery)<|endoftext|>


<commit_before>import React from 'react';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';

export default class Example extends React.Component {
  render() {
    return (
      <Form inline>
        <FormGroup>
          Email{' '}
          <Input type="email" name="email" id="exampleEmail" placeholder="something@idk.cool" />
        </FormGroup>
        {' '}
        <FormGroup>
          Password{' '}
          <Input type="password" name="password" id="examplePassword" placeholder="don't tell!" />
        </FormGroup>
        {' '}
        <Button>Submit</Button>
      </Form>
    );
  }
}
<commit_msg>chore(docs): update inline form spacing (#702)<commit_after>import React from 'react';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';

export default class Example extends React.Component {
  render() {
    return (
      <Form inline>
        <FormGroup className="mb-2 mr-sm-2 mb-sm-0">
          Email
          <Input type="email" name="email" id="exampleEmail" placeholder="something@idk.cool" />
        </FormGroup>
        <FormGroup className="mb-2 mr-sm-2 mb-sm-0">
          Password
          <Input type="password" name="password" id="examplePassword" placeholder="don't tell!" />
        </FormGroup>
        <Button>Submit</Button>
      </Form>
    );
  }
}
<|endoftext|>


<commit_before>var View = require('./view');
var Graph = require('../models/graph');

module.exports = View.extend({

    model:Graph,

    initialize:function () {
        _.bindAll(this, 'render', 'showData');
    },

    afterRender:function () {
        this.$el.addClass('parcoords').attr('id', 'test');
        this.model.on('load', this.showData);
    },

    showData:function () {
        var nodes = this.model.get("nodes");
        var keys = _.difference(_.keys(nodes[0]), ['label', 'type', 'source', 'feature_id', 'nByi']);

        var pc = d3.parcoords()('#test');

        pc.dimensions(keys)
            .data(nodes)
            .render()
            .color("#000")
            .alpha(0.3)
            .margin({ top:30, left:0, bottom:12, right:0 })
            .render()
            .reorderable()
            .brushable()
            .on('brush', this.model.filterNodes);

        pc.svg.selectAll(".parcoords-dimension")
            .on("click", toggle_dimension);

        function select(dimension) {
            pc.svg.selectAll(".parcoords-dimension")
                .filter(function (d) {
                    return d == dimension;
                })
                .classed('selected', true);
        }

        function unselect() {
            pc.svg.selectAll(".parcoords-dimension")
                .classed('selected', false);
        }

        function toggle_dimension(dimension) {

            var dim = pc.svg.selectAll(".parcoords-dimension.selected")
                .filter(function (d) {
                    return d == dimension;
                });

            if (dim[0].length > 0) {  //this was previously selected
                unselect();
                Backbone.Events.trigger('');
                console.log('previous');
            } else {    //this was not previously selected
                unselect();
                select(dimension);
                Backbone.Mediator.pub('dimension:select', dimension);
            }
        }

    }
});<commit_msg>removed _pos field from elements to be filtered by<commit_after>var View = require('./view');
var Graph = require('../models/graph');

module.exports = View.extend({

    model:Graph,

    initialize:function () {
        _.bindAll(this, 'render', 'showData');
    },

    afterRender:function () {
        this.$el.addClass('parcoords').attr('id', 'test');
        this.model.on('load', this.showData);
    },

    showData:function () {
        var nodes = this.model.get("nodes");
        var keys = _.difference(_.keys(nodes[0]), ['label', 'type', 'source', 'feature_id', 'nByi', '_pos']);

        var pc = d3.parcoords()('#test');

        pc.dimensions(keys)
            .data(nodes)
            .render()
            .color("#000")
            .alpha(0.3)
            .margin({ top:30, left:0, bottom:12, right:0 })
            .render()
            .reorderable()
            .brushable()
            .on('brush', this.model.filterNodes);

        pc.svg.selectAll(".parcoords-dimension")
            .on("click", toggle_dimension);

        function select(dimension) {
            pc.svg.selectAll(".parcoords-dimension")
                .filter(function (d) {
                    return d == dimension;
                })
                .classed('selected', true);
        }

        function unselect() {
            pc.svg.selectAll(".parcoords-dimension")
                .classed('selected', false);
        }

        function toggle_dimension(dimension) {

            var dim = pc.svg.selectAll(".parcoords-dimension.selected")
                .filter(function (d) {
                    return d == dimension;
                });

            if (dim[0].length > 0) {  //this was previously selected
                unselect();
                Backbone.Events.trigger('');
                console.log('previous');
            } else {    //this was not previously selected
                unselect();
                select(dimension);
                Backbone.Mediator.pub('dimension:select', dimension);
            }
        }

    }
});<|endoftext|>


<commit_before>'use strict';

describe('MarkupCtrl', function(){

    var $rootScope, $scope, $controller;
    var markupAmounts;
    var MarkupCtrl;
    var markups;

  beforeEach(module('myApp.view1'));

  beforeEach(inject(function(_$rootScope_, _$controller_, _markupAmounts_) {

       // I have learned that order is important
       // I also learned that case must match service injection case ..
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $controller = _$controller_;
        markupAmounts = _markupAmounts_;

        MarkupCtrl = $controller('MarkupCtrl', {

            '$rootScope': _$rootScope_,
            '$scope':$scope,
            'markupAmounts':_markupAmounts_

        });

 }));

 describe("MarkupCtrl controller to be definedddd", function() {

     it("MarkupCtrl controller should be defined", function () {
         expect(MarkupCtrl).toBeDefined();
     });
     it("$scope.markups should be defined ", function () {
         expect($scope.markups).toBeDefined();
     });

    });

    describe(' testing for service ...', function() {
      describe('markupAmounts service mock', function() {
        var createService;
      // beforeEach(module('myApp.view1'));
        beforeEach(inject(function() {
          var $injector = angular.injector(['myApp.view1'])

          createService = function() {
            return $injector.get('markupAmounts');
          }
        }));

        it('service should be defined', function(){
          var service = createService();
          expect(service).toBeDefined();
        });

        it('service should be an object', function(){
          var service = createService();
        expect(service).toEqual(jasmine.any(Object));
        });

      });
    });

});
<commit_msg>mocked up scope object to run tests on Test block checks that object type matches expected object type Checks that price isn't a string checks that a startRate has been set (1299.99) 	modified:   app/view1/view1_test.js<commit_after>'use strict';

describe('MarkupCtrl', function(){

    var $rootScope, $scope, $controller;
    var markupAmounts;
    var MarkupCtrl;
    var markups;

  beforeEach(module('myApp.view1'));

  beforeEach(inject(function(_$rootScope_, _$controller_, _markupAmounts_) {

       // I have learned that order is important
       // I also learned that case must match service injection case ..
        $rootScope = _$rootScope_;
        $scope = $rootScope.$new();
        $controller = _$controller_;
        markupAmounts = _markupAmounts_;

        MarkupCtrl = $controller('MarkupCtrl', {

            '$rootScope': _$rootScope_,
            '$scope':$scope,
            'markupAmounts':_markupAmounts_

        });

 }));

 beforeEach(function() {
   //mocking up scope object
     markups = {
       startRate: 1299.99,
       numberOfPeople: 3,
       price: Function,
       people: Function,
       isFood:Function,
       isElectronic:Function,
       isPharm: Function,
       finalCost:Function
     };
   });

 describe("MarkupCtrl controller to be definedddd", function() {

     it("MarkupCtrl controller should be defined", function () {
         expect(MarkupCtrl).toBeDefined();
     });
     it("$scope.markups should be defined ", function () {
         expect($scope.markups).toBeDefined();
     });
     //tests on scope object
     it("matches object type with the expect key/value pairs", function() {
         expect(markups).toEqual(jasmine.objectContaining({
           startRate: 1299.99
         }));
         expect(markups).not.toEqual(jasmine.objectContaining({
           price: ''
         }));
         expect(markups).toEqual(jasmine.objectContaining({
          //  startRate:Number, //will fail
           startRate:1299.99, // will pass
           numberOfPeople: 3,
           people: Function,
           price: Function,
           isFood: Function,
           isElectronic: Function,
           isPharm: Function,
           finalCost: Function
         }))
          expect(markups.startRate).toEqual(jasmine.any(Number));
          expect(markups.numberOfPeople).toEqual(jasmine.any(Number));
          expect(markups.people).toEqual(jasmine.any(Function));
          expect(markups.price).toEqual(jasmine.any(Function));
          expect(markups.isFood).toEqual(jasmine.any(Function));
          expect(markups.isElectronic).toEqual(jasmine.any(Function));
          expect(markups.isPharm).toEqual(jasmine.any(Function));
          expect(markups.finalCost).toEqual(jasmine.any(Function));

       });

    });

    describe(' testing for service ...', function() {
      describe('markupAmounts service mock', function() {
        var createService;
      // beforeEach(module('myApp.view1'));
        beforeEach(inject(function() {
          var $injector = angular.injector(['myApp.view1'])

          createService = function() {
            return $injector.get('markupAmounts');
          }
        }));

        it('service should be defined', function(){
          var service = createService();
          expect(service).toBeDefined();
        });

        it('service should be an object', function(){
          var service = createService();
        expect(service).toEqual(jasmine.any(Object));
        });

      });
    });

});
<|endoftext|>


<commit_before>// JQuery URL Parser plugin - https://github.com/allmarkedup/jQuery-URL-Parser
// Written by Mark Perkins, mark@allmarkedup.com
// License: http://unlicense.org/ (i.e. do what you want with it!)

;(function($, undefined) {

    var tag2attr = {
        a       : 'href',
        img     : 'src',
        form    : 'action',
        base    : 'href',
        script  : 'src',
        iframe  : 'src',
        link    : 'href'
    },

	key = ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","fragment"], // keys available to query

	aliases = { "anchor" : "fragment" }, // aliases for backwards compatability

	parser = {
		strict  : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,  //less intuitive, more accurate to the specs
		loose   :  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
	},

	querystring_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g, // supports both ampersand and semicolon-delimted query string key/value pairs

	fragment_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g; // supports both ampersand and semicolon-delimted fragment key/value pairs

	function parseUri( url, strictMode )
	{
		var str = decodeURI( url ),
		    res   = parser[ strictMode || false ? "strict" : "loose" ].exec( str ),
		    uri = { attr : {}, param : {}, seg : {} },
		    i   = 14;

		while ( i-- )
		{
			uri.attr[ key[i] ] = res[i] || "";
		}

		// build query and fragment parameters

		uri.param['query'] = {};
		uri.param['fragment'] = {};

		uri.attr['query'].replace( querystring_parser, function ( $0, $1, $2 ){
			if ($1)
			{
				uri.param['query'][$1] = $2;
			}
		});

		uri.attr['fragment'].replace( fragment_parser, function ( $0, $1, $2 ){
			if ($1)
			{
				uri.param['fragment'][$1] = $2;
			}
		});

		// split path and fragement into segments

        uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');

        uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');

        // compile a 'base' domain attribute

        uri.attr['base'] = uri.attr.host ? uri.attr.protocol+"://"+uri.attr.host + (uri.attr.port ? ":"+uri.attr.port : '') : '';

		return uri;
	};

	function getAttrName( elm )
	{
		var tn = elm.tagName;
		if ( tn !== undefined ) return tag2attr[tn.toLowerCase()];
		return tn;
	}

	$.fn.url = function( strictMode )
	{
	    var url = '';

	    if ( this.length )
	    {
	        url = $(this).attr( getAttrName(this[0]) ) || '';
	    }

        return $.url({ url : url, strict : strictMode });
	};

	$.url = function( opts )
	{
	    var url     = '',
	        strict  = false;

	    if ( typeof opts === 'string' )
	    {
	        url = opts;
	    }
	    else
	    {
	        opts = opts || {};
	        strict = opts.strict || strict;
            url = opts.url === undefined ? window.location.toString() : opts.url;
	    }

        return {

            data : parseUri(url, strict),

            // get various attributes from the URI
            attr : function( attr )
            {
                attr = aliases[attr] || attr;
                return attr !== undefined ? this.data.attr[attr] : this.data.attr;
            },

            // return query string parameters
            param : function( param )
            {
                return param !== undefined ? this.data.param.query[param] : this.data.param.query;
            },

            // return fragment parameters
            fparam : function( param )
            {
                return param !== undefined ? this.data.param.fragment[param] : this.data.param.fragment;
            },

            // return path segments
            segment : function( seg )
            {
                if ( seg === undefined )
                {
                    return this.data.seg.path;
                }
                else
                {
                    seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
                    return this.data.seg.path[seg];
                }
            },

            // return fragment segments
            fsegment : function( seg )
            {
                if ( seg === undefined )
                {
                    return this.data.seg.fragment;
                }
                else
                {
                    seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
                    return this.data.seg.fragment[seg];
                }
            }

        };

	};

})(jQuery);<commit_msg>Tidy up the way 'strict' mode is triggered.<commit_after>// JQuery URL Parser plugin - https://github.com/allmarkedup/jQuery-URL-Parser
// Written by Mark Perkins, mark@allmarkedup.com
// License: http://unlicense.org/ (i.e. do what you want with it!)

;(function($, undefined) {

    var tag2attr = {
        a       : 'href',
        img     : 'src',
        form    : 'action',
        base    : 'href',
        script  : 'src',
        iframe  : 'src',
        link    : 'href'
    },

	key = ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","fragment"], // keys available to query

	aliases = { "anchor" : "fragment" }, // aliases for backwards compatability

	parser = {
		strict  : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,  //less intuitive, more accurate to the specs
		loose   :  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs
	},

	querystring_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g, // supports both ampersand and semicolon-delimted query string key/value pairs

	fragment_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g; // supports both ampersand and semicolon-delimted fragment key/value pairs

	function parseUri( url, strictMode )
	{
		var str = decodeURI( url ),
		    res   = parser[ strictMode || false ? "strict" : "loose" ].exec( str ),
		    uri = { attr : {}, param : {}, seg : {} },
		    i   = 14;

		while ( i-- )
		{
			uri.attr[ key[i] ] = res[i] || "";
		}

		// build query and fragment parameters

		uri.param['query'] = {};
		uri.param['fragment'] = {};

		uri.attr['query'].replace( querystring_parser, function ( $0, $1, $2 ){
			if ($1)
			{
				uri.param['query'][$1] = $2;
			}
		});

		uri.attr['fragment'].replace( fragment_parser, function ( $0, $1, $2 ){
			if ($1)
			{
				uri.param['fragment'][$1] = $2;
			}
		});

		// split path and fragement into segments

        uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');

        uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');

        // compile a 'base' domain attribute

        uri.attr['base'] = uri.attr.host ? uri.attr.protocol+"://"+uri.attr.host + (uri.attr.port ? ":"+uri.attr.port : '') : '';

		return uri;
	};

	function getAttrName( elm )
	{
		var tn = elm.tagName;
		if ( tn !== undefined ) return tag2attr[tn.toLowerCase()];
		return tn;
	}

	$.fn.url = function( strictMode )
	{
	    var url = '';

	    if ( this.length )
	    {
	        url = $(this).attr( getAttrName(this[0]) ) || '';
	    }

        return $.url( url, strictMode );
	};

	$.url = function( url, strictMode )
	{
	    if ( arguments.length === 1 && url === true )
        {
            strictMode = true;
            url = undefined;
        }

        strictMode = strictMode || false;
        url = url || window.location.toString();

        return {

            data : parseUri(url, strictMode),

            // get various attributes from the URI
            attr : function( attr )
            {
                attr = aliases[attr] || attr;
                return attr !== undefined ? this.data.attr[attr] : this.data.attr;
            },

            // return query string parameters
            param : function( param )
            {
                return param !== undefined ? this.data.param.query[param] : this.data.param.query;
            },

            // return fragment parameters
            fparam : function( param )
            {
                return param !== undefined ? this.data.param.fragment[param] : this.data.param.fragment;
            },

            // return path segments
            segment : function( seg )
            {
                if ( seg === undefined )
                {
                    return this.data.seg.path;
                }
                else
                {
                    seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end
                    return this.data.seg.path[seg];
                }
            },

            // return fragment segments
            fsegment : function( seg )
            {
                if ( seg === undefined )
                {
                    return this.data.seg.fragment;
                }
                else
                {
                    seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end
                    return this.data.seg.fragment[seg];
                }
            }

        };

	};

})(jQuery);<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import styled from 'styled-components';
import Box from 'grommet/components/Box';
import Label from 'grommet/components/Label';
import Heading from 'grommet/components/Heading';
import PlayIcon from 'grommet/components/icons/base/CirclePlay';
import Markdown from 'grommet/components/Markdown';
import unescape from 'unescape';

const ImageBox = styled(Box)`
  padding-bottom: 56%;
  background-position: 50% 50%;
  position: relative;
  @media all and (-ms-high-contrast:none) {
    height: 263px;
  }
`;

const InnerImageBox = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
`;

const Icon = styled(PlayIcon)`
  max-height: 100%;
`;

export default function VideoCallout({ label, onClick, description, thumbnail }) {
  const markdownContent = unescape(description || '');
  return (

      {label && {label}}
      <ImageBox
        full="horizontal"
        align="center"
        justify="center"
        texture={thumbnail}
        onClick={onClick}
      >
        <InnerImageBox>
          <Icon size="xlarge" colorIndex="brand" />
        </InnerImageBox>
      </ImageBox>
      <Markdown
        content={markdownContent}
        components={{
          p: { props: { size: 'medium', margin: 'small', align: 'start' } },
          h1: { props: { margin: 'none', align: 'start' } },
          h2: { props: { margin: 'none', align: 'start' } },
          h3: { props: { margin: 'none', align: 'start' } },
          h4: { props: { margin: 'none', align: 'start' } },
          h5: { props: { margin: 'none', align: 'start' } },
        }}
      />

  );
}

VideoCallout.propTypes = {
  description: PropTypes.string,
  label: PropTypes.string,
  onClick: PropTypes.func,
  thumbnail: PropTypes.string,
};

VideoCallout.defaultProps = {
  thumbnail: '/img/dashboard/video-thumb.jpg',
};
<commit_msg>Fix video padding bug.<commit_after>import React, { PropTypes } from 'react';
import styled from 'styled-components';
import Box from 'grommet/components/Box';
import Label from 'grommet/components/Label';
import Heading from 'grommet/components/Heading';
import PlayIcon from 'grommet/components/icons/base/CirclePlay';
import Markdown from 'grommet/components/Markdown';
import unescape from 'unescape';

const ImageBox = styled(Box)`
  padding-bottom: 56% !important;
  background-position: 50% 50%;
  position: relative;
  @media all and (-ms-high-contrast:none) {
    height: 263px;
  }
`;

const InnerImageBox = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
`;

const Icon = styled(PlayIcon)`
  max-height: 100%;
`;

export default function VideoCallout({ label, onClick, description, thumbnail }) {
  const markdownContent = unescape(description || '');
  return (

      {label && {label}}
      <ImageBox
        full="horizontal"
        align="center"
        justify="center"
        texture={thumbnail}
        onClick={onClick}
      >
        <InnerImageBox>
          <Icon size="xlarge" colorIndex="brand" />
        </InnerImageBox>
      </ImageBox>
      <Markdown
        content={markdownContent}
        components={{
          p: { props: { size: 'medium', margin: 'small', align: 'start' } },
          h1: { props: { margin: 'none', align: 'start' } },
          h2: { props: { margin: 'none', align: 'start' } },
          h3: { props: { margin: 'none', align: 'start' } },
          h4: { props: { margin: 'none', align: 'start' } },
          h5: { props: { margin: 'none', align: 'start' } },
        }}
      />

  );
}

VideoCallout.propTypes = {
  description: PropTypes.string,
  label: PropTypes.string,
  onClick: PropTypes.func,
  thumbnail: PropTypes.string,
};

VideoCallout.defaultProps = {
  thumbnail: '/img/dashboard/video-thumb.jpg',
};
<|endoftext|>


<commit_before>function draw(){
    buffer.clearRect(
      0,
      0,
      width,
      height
    );

    buffer.save()

    buffer.translate(
      x,
      y
    );

    buffer.strokeStyle = '#fff';
    for(var vertex in vertices){
        buffer.beginPath();
        buffer.moveTo(
          vertices[vertex]['dx'],
          vertices[vertex]['dy']
        );
        buffer.lineTo(
          vertices[vertex]['dx'],
          vertices[vertices[vertex]['parent']]['dy']
        );
        buffer.closePath();
        buffer.stroke();

        buffer.beginPath();
        buffer.moveTo(
          vertices[vertex]['dx'],
          vertices[vertices[vertex]['parent']]['dy']
        );
        buffer.lineTo(
          vertices[vertices[vertex]['parent']]['dx'],
          vertices[vertices[vertex]['parent']]['dy']
        );
        buffer.closePath();
        buffer.stroke();
    }

    buffer.restore();

    canvas.clearRect(
      0,
      0,
      width,
      height
    );
    canvas.drawImage(
      document.getElementById('buffer'),
      0,
      0
    );

    window.requestAnimationFrame(draw);
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] += vertices[vertex]['speed'];
        if(vertices[vertex]['loop'] > 359){
            vertices[vertex]['loop'] -= 360;
        }else if(vertices[vertex]['loop']){
            vertices[vertex]['loop'] += 360;
        }

        vertices[vertex]['dx'] =
          vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(vertices[vertex]['loop'] * pi_divide_180);
        vertices[vertex]['dy'] =
          vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(vertices[vertex]['loop'] * pi_divide_180)
    }
}

function randomize(){
    for(var vertex in vertices){
        vertices[vertex] = {
          'dx': 0,
          'dy': 0,
          'loop': Math.floor(Math.random() * 50) + 50,
          'parent': vertex - 1,
          'radius': Math.random() * 20 + 5,
          'speed': Math.floor(Math.random() * 10) - 5 * 2,
          'x': Math.floor(Math.random() * 500) - 250,
          'y': Math.floor(Math.random() * 500) - 250,
        };
    }
    vertices[0]['parent'] = vertices.length - 1;
}

function resize(){
    height = window.innerHeight;
    document.getElementById('buffer').height = height;
    document.getElementById('canvas').height = height;
    y = height / 2;

    width = window.innerWidth;
    document.getElementById('buffer').width = width;
    document.getElementById('canvas').width = width;
    x = width / 2;
}

var buffer = document.getElementById('buffer').getContext('2d');
var canvas = document.getElementById('canvas').getContext('2d');
var height = 0;
var loop = 0;
var pi_divide_180 = Math.PI / 180;
var vertices = [];
var width = 0;
var x = 0;
var y = 0;

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    // R: randomize vertices.
    if(key == 82){
        randomize();
    }
};

window.onload = function(e){
    resize();

    var loop_counter = 23;
    do{
        vertices.push({});
    }while(loop_counter--);
    randomize();

    window.requestAnimationFrame(draw);
    window.setInterval(
      'logic()',
      30
    );
};

window.onresize = resize;
<commit_msg>removed unnecessary variable<commit_after>function draw(){
    buffer.clearRect(
      0,
      0,
      width,
      height
    );

    buffer.save()

    buffer.translate(
      x,
      y
    );

    buffer.strokeStyle = '#fff';
    for(var vertex in vertices){
        buffer.beginPath();
        buffer.moveTo(
          vertices[vertex]['dx'],
          vertices[vertex]['dy']
        );
        buffer.lineTo(
          vertices[vertex]['dx'],
          vertices[vertices[vertex]['parent']]['dy']
        );
        buffer.closePath();
        buffer.stroke();

        buffer.beginPath();
        buffer.moveTo(
          vertices[vertex]['dx'],
          vertices[vertices[vertex]['parent']]['dy']
        );
        buffer.lineTo(
          vertices[vertices[vertex]['parent']]['dx'],
          vertices[vertices[vertex]['parent']]['dy']
        );
        buffer.closePath();
        buffer.stroke();
    }

    buffer.restore();

    canvas.clearRect(
      0,
      0,
      width,
      height
    );
    canvas.drawImage(
      document.getElementById('buffer'),
      0,
      0
    );

    window.requestAnimationFrame(draw);
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] += vertices[vertex]['speed'];
        if(vertices[vertex]['loop'] > 359){
            vertices[vertex]['loop'] -= 360;
        }else if(vertices[vertex]['loop']){
            vertices[vertex]['loop'] += 360;
        }

        vertices[vertex]['dx'] =
          vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(vertices[vertex]['loop'] * pi_divide_180);
        vertices[vertex]['dy'] =
          vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(vertices[vertex]['loop'] * pi_divide_180)
    }
}

function randomize(){
    for(var vertex in vertices){
        vertices[vertex] = {
          'dx': 0,
          'dy': 0,
          'loop': Math.floor(Math.random() * 50) + 50,
          'parent': vertex - 1,
          'radius': Math.random() * 20 + 5,
          'speed': Math.floor(Math.random() * 10) - 5 * 2,
          'x': Math.floor(Math.random() * 500) - 250,
          'y': Math.floor(Math.random() * 500) - 250,
        };
    }
    vertices[0]['parent'] = vertices.length - 1;
}

function resize(){
    height = window.innerHeight;
    document.getElementById('buffer').height = height;
    document.getElementById('canvas').height = height;
    y = height / 2;

    width = window.innerWidth;
    document.getElementById('buffer').width = width;
    document.getElementById('canvas').width = width;
    x = width / 2;
}

var buffer = document.getElementById('buffer').getContext('2d');
var canvas = document.getElementById('canvas').getContext('2d');
var height = 0;
var pi_divide_180 = Math.PI / 180;
var vertices = [];
var width = 0;
var x = 0;
var y = 0;

window.onkeydown = function(e){
    var key = e.keyCode || e.which;

    // R: randomize vertices.
    if(key == 82){
        randomize();
    }
};

window.onload = function(e){
    resize();

    var loop_counter = 23;
    do{
        vertices.push({});
    }while(loop_counter--);
    randomize();

    window.requestAnimationFrame(draw);
    window.setInterval(
      'logic()',
      30
    );
};

window.onresize = resize;
<|endoftext|>


<commit_before>const fetch = require('node-fetch');
const _ = require('lodash');
const { validOrganism } = require('./validity-info');
const { validTargetDb } = require('./validity-info');
const qs = require('query-string');
const { cleanUpEntrez } = require('../helper');

const GCONVERT_URL = 'https://biit.cs.ut.ee/gprofiler_archive3/r1741_e90_eg37/web/gconvert.cgi';
const FETCH_TIMEOUT = 5000; //ms

class InvalidParameterError extends Error {
  constructor( message ) {
    super( message );
    this.name = 'InvalidParameterError';
  }
}

const resultTemplate = ( unrecognized, duplicate, geneInfo ) => {
  return {
    unrecognized: Array.from( unrecognized ) || [],
    duplicate: duplicate || {},
    geneInfo: geneInfo || []
  };
};

/* errorHandler
 * This function routes errors in a rational manner: Fetch-related errors are gently handled
 * by returning the original gene list as 'unrecognized'; For input errors, the Promise is
 * rejected with the error info for the client; in all other cases an Error is thrown.
 * @param { object } data - 'error' and 'query' (optional) keys
 *
 */
const errorHandler = ( data ) => {
  if ( data.error instanceof Error ) {
    switch ( data.error.name ) {
      case 'InvalidParameterError':
        return new Promise( ( _, reject ) => reject( { "Error": data.error.message } ) );
      case 'FetchError':
      default:
        return new Promise( resolve => resolve( resultTemplate( data.query ) ) );
    }

  } else {
    throw new Error(' something wrong ');
  }
};

const bodyHandler = body =>  {
  const geneInfoList = _.map(body.split('\n'), ele => { return ele.split('\t'); });
  geneInfoList.splice(-1, 1); // remove last element ''
  const unrecognized = new Set();
  let duplicate = {};
  const previous = new Map();
  let geneInfo = new Set();
  const initialAliasIndex = 1;
  const convertedAliasIndex = 3;
  _.forEach(geneInfoList, info => {
    const convertedAlias = info[convertedAliasIndex];
    let initialAlias = info[initialAliasIndex];
    initialAlias = cleanUpEntrez(initialAlias);
    if (convertedAlias === 'N/A') {
      unrecognized.add(initialAlias);
    } else {
      if (!previous.has(convertedAlias)) {
        previous.set(convertedAlias, initialAlias);
      } else {
        if (!(convertedAlias in duplicate)) {
          duplicate[convertedAlias] = new Set([previous.get(convertedAlias)]);
        }
        duplicate[convertedAlias].add(initialAlias);
      }
      geneInfo.add(JSON.stringify({initialAlias: initialAlias, convertedAlias: convertedAlias}));
    }
  });
  for (const initialAlias in duplicate) {
    duplicate[initialAlias] = Array.from(duplicate[initialAlias]);
  }
  geneInfo = _.map(Array.from(geneInfo), ele => { return JSON.parse(ele); });
  return resultTemplate( unrecognized, duplicate, geneInfo );
};

const mapDBNames = officalSynonym  => {
  officalSynonym = officalSynonym.toUpperCase();
  if ( officalSynonym === 'HGNCSYMBOL' ) { return 'HGNC'; }
  if ( officalSynonym === 'HGNC' ) { return 'HGNC_ACC'; }
  if ( officalSynonym === 'UNIPROT' ) { return 'UNIPROTSWISSPROT'; }
  if ( officalSynonym === 'NCBIGENE' ) { return 'ENTREZGENE_ACC'; }
  return officalSynonym;
};

/*
 * getForm
 * @param { array } query - Gene IDs
 * @param { object } userOptions
 * @returns { object } error and form
 */
const getForm = ( query, defaultOptions, userOptions ) => {

  let error;
  const form = _.assign( {},
    defaultOptions,
    JSON.parse( JSON.stringify( userOptions ) ),
    { query: query }
  );

  if (!Array.isArray( form.query )) {
    error = new InvalidParameterError( 'Invalid genes: Must be an array' );
  }
  if ( !validOrganism.includes( form.organism.toLowerCase() ) ) {
    error = new InvalidParameterError( 'Invalid organism' );
  }
  if ( !validTargetDb.includes( form.target.toUpperCase() ) ) {
    error = new InvalidParameterError( 'Invalid target' );
  }

  form.target = mapDBNames( form.target );
  form.query = form.query.join(" ");

  return {
    form: form,
    error: error
  };
};

/* validatorGconvert
 * @param { array } query - identifier list query
 * @param { object } userOptions - options
 * @return { object } list of unrecognized, object with duplicated and list of mapped IDs
 */
const validatorGconvert = ( query, userOptions ) => {

  const defaultOptions = {
    'output': 'mini',
    'organism': 'hsapiens',
    'target': 'HGNC',
    'prefix': 'ENTREZGENE_ACC'
  };

  return new Promise( ( resolve, reject ) => {

    const formData = getForm( query, defaultOptions, userOptions );
    if ( formData.error ) reject( { error: formData.error } );
    fetch( GCONVERT_URL, {
        method: 'post',
        body: qs.stringify( formData.form ),
        timeout: FETCH_TIMEOUT
    })
    .then( response => response.text() )
    .then( bodyHandler )
    .then( resolve )
    .catch( error => {
      reject( { error: error, query: query } );
    });
  })
  .catch( errorHandler );
};

module.exports = { validatorGconvert };
<commit_msg>Improved the error passing/catch in form<commit_after>const fetch = require('node-fetch');
const _ = require('lodash');
const { validOrganism } = require('./validity-info');
const { validTargetDb } = require('./validity-info');
const qs = require('query-string');
const { cleanUpEntrez } = require('../helper');

const GCONVERT_URL = 'https://biit.cs.ut.ee/gprofiler_archive3/r1741_e90_eg37/web/gconvert.cgi';
const FETCH_TIMEOUT = 5000; //ms

class InvalidParameterError extends Error {
  constructor( message ) {
    super( message );
    this.name = 'InvalidParameterError';
  }
}

const resultTemplate = ( unrecognized, duplicate, geneInfo ) => {
  return {
    unrecognized: Array.from( unrecognized ) || [],
    duplicate: duplicate || {},
    geneInfo: geneInfo || []
  };
};

const mapDBNames = officalSynonym  => {
  officalSynonym = officalSynonym.toUpperCase();
  if ( officalSynonym === 'HGNCSYMBOL' ) { return 'HGNC'; }
  if ( officalSynonym === 'HGNC' ) { return 'HGNC_ACC'; }
  if ( officalSynonym === 'UNIPROT' ) { return 'UNIPROTSWISSPROT'; }
  if ( officalSynonym === 'NCBIGENE' ) { return 'ENTREZGENE_ACC'; }
  return officalSynonym;
};

/*
 * getForm
 * @param { array } query - Gene IDs
 * @param { object } userOptions
 * @returns { object } error and form
 */
const getForm = ( query, defaultOptions, userOptions ) => {

  const form = _.assign( {},
    defaultOptions,
    JSON.parse( JSON.stringify( userOptions ) ),
    { query: query }
  );

  if (!Array.isArray( form.query )) {
    throw new InvalidParameterError( 'Invalid genes: Must be an array' );
  }
  if ( !validOrganism.includes( form.organism.toLowerCase() ) ) {
    throw new InvalidParameterError( 'Invalid organism' );
  }
  if ( !validTargetDb.includes( form.target.toUpperCase() ) ) {
    throw new InvalidParameterError( 'Invalid target' );
  }

  form.target = mapDBNames( form.target );
  form.query = form.query.join(" ");

  return form;
};

const bodyHandler = body =>  {
  const geneInfoList = _.map(body.split('\n'), ele => { return ele.split('\t'); });
  geneInfoList.splice(-1, 1); // remove last element ''
  const unrecognized = new Set();
  let duplicate = {};
  const previous = new Map();
  let geneInfo = new Set();
  const initialAliasIndex = 1;
  const convertedAliasIndex = 3;
  _.forEach(geneInfoList, info => {
    const convertedAlias = info[convertedAliasIndex];
    let initialAlias = info[initialAliasIndex];
    initialAlias = cleanUpEntrez(initialAlias);
    if (convertedAlias === 'N/A') {
      unrecognized.add(initialAlias);
    } else {
      if (!previous.has(convertedAlias)) {
        previous.set(convertedAlias, initialAlias);
      } else {
        if (!(convertedAlias in duplicate)) {
          duplicate[convertedAlias] = new Set([previous.get(convertedAlias)]);
        }
        duplicate[convertedAlias].add(initialAlias);
      }
      geneInfo.add(JSON.stringify({initialAlias: initialAlias, convertedAlias: convertedAlias}));
    }
  });
  for (const initialAlias in duplicate) {
    duplicate[initialAlias] = Array.from(duplicate[initialAlias]);
  }
  geneInfo = _.map(Array.from(geneInfo), ele => { return JSON.parse(ele); });
  return resultTemplate( unrecognized, duplicate, geneInfo );
};

/* errorHandler
 * This function routes errors in a rational manner: Fetch-related errors are gently handled
 * by returning the original gene list as 'unrecognized'; For input errors, the Promise is
 * rejected with the error info for the client; in all other cases an Error is thrown.
 * @param { object } data - Error object and query (optional)
 * @return { Promise }
 */
const errorHandler = ( error, query ) => {
  console.error( error );
  switch ( error.name ) {
    case 'FetchError':
      return new Promise( resolve => resolve( resultTemplate( query ) ) );
    case 'InvalidParameterError':
    default:
      return new Promise( ( _, reject ) => reject( { "Error": error.message } ) );
  }
};

/* validatorGconvert
 * @param { array } query - identifier list query
 * @param { object } userOptions - options
 * @return { object } list of unrecognized, object with duplicated and list of mapped IDs
 */
const validatorGconvert = ( query, userOptions ) => {

  const defaultOptions = {
    'output': 'mini',
    'organism': 'hsapiens',
    'target': 'HGNC',
    'prefix': 'ENTREZGENE_ACC'
  };

  return new Promise(( resolve, reject ) => {

    const form = getForm( query, defaultOptions, userOptions );
    fetch( GCONVERT_URL, {
        method: 'post',
        body: qs.stringify( form ),
        timeout: FETCH_TIMEOUT
    })
    .then( response => response.text() )
    .then( bodyHandler )
    .then( resolve )
    .catch( reject );
  })
  .catch( error => errorHandler( error, query ) );
};

module.exports = { validatorGconvert };
<|endoftext|>


<commit_before>// Copyright 2019-2020, University of Colorado Boulder

/**
 * Event & listener abstraction for a single "event" type. The type provides extra functionality beyond just notifying
 * listeners. It adds PhET-iO instrumentation capabilities as well as validation. For the lightest-weight, fastest
 * solution with the smallest memory footprint, see `TinyEmitter`.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Michael Kauzmann (PhET Interactive Simulations)
 */

import merge from '../../phet-core/js/merge.js';
import FunctionIO from '../../tandem/js/types/FunctionIO.js';
import ObjectIO from '../../tandem/js/types/ObjectIO.js';
import VoidIO from '../../tandem/js/types/VoidIO.js';
import Action from './Action.js';
import axon from './axon.js';
import TinyEmitter from './TinyEmitter.js';

class Emitter extends Action {

  /**
   * @param {Object} [options]
   */
  constructor( options ) {

    options = merge( {
      phetioOuterType: Emitter.createEmitterIO
    }, options );

    super( function() {
      assert && assert( self.tinyEmitter instanceof TinyEmitter,
        'Emitter should not emit until after its constructor has completed' );

      self.tinyEmitter.emit.apply( self.tinyEmitter, arguments );
    }, options );

    const self = this;

    // @private - provide Emitter functionality via composition
    this.tinyEmitter = new TinyEmitter();
  }

  /**
   * Emitter instances should not be calling Action.execute, instead see Emitter.emit().
   * See the second half of https://github.com/phetsims/axon/issues/243 for discussion.
   * @override
   * @public
   */
  execute() {
    assert && assert( false, 'This should not be called, use Emitter.emit() instead.' );
  }

  /**
   * Emit to notify listeners; implemented by executing the action of the parent class.
   * @public
   * @params {*}
   */
  emit() {
    super.execute.apply( this, arguments );
  }

  /**
   * Disposes an Emitter. All listeners are removed.
   * @public
   * @override
   */
  dispose() {
    this.tinyEmitter.dispose();
    super.dispose();
  }

  /**
   * Adds a listener which will be called during emit.
   * @param {function} listener
   * @public
   */
  addListener( listener ) {
    this.tinyEmitter.addListener( listener );
  }

  /**
   * Removes a listener
   * @param {function} listener
   * @public
   */
  removeListener( listener ) {
    this.tinyEmitter.removeListener( listener );
  }

  /**
   * Removes all the listeners
   * @public
   */
  removeAllListeners() {
    this.tinyEmitter.removeAllListeners();
  }

  /**
   * Checks whether a listener is registered with this Emitter
   * @param {function} listener
   * @returns {boolean}
   * @public
   */
  hasListener( listener ) {
    return this.tinyEmitter.hasListener( listener );
  }

  /**
   * Returns true if there are any listeners.
   * @returns {boolean}
   * @public
   */
  hasListeners() {
    return this.tinyEmitter.hasListeners();
  }

  /**
   * Returns the number of listeners.
   * @returns {number}
   * @public
   */
  getListenerCount() {
    return this.tinyEmitter.getListenerCount();
  }
}

const paramToTypeName = param => param.typeName;
const cache = {};

/**
 * IO Type for Emitter.
 *
 * Providing validators to instrumented Emitters:
 * Instrumented Emitters should have their `validators` for each argument passed via EmitterIO (the phetioType).
 * To provide validators, there are two methods. First, by default each TypeIO has its own
 * validator that will be used. So specifying an argument object like `{ type: NumberIO }` will automatically use
 * `NumberIO.validator` as the validator. This can be overridden with the `validator` key (second option), like
 * { type: NumberIO, validator: { isValidValue: v=> typeof v === 'number' &&  v < 5 } }`
 * NOTE: currently the implementation is either/or, if a validator is provided via the `validator` key, the validator
 * from the `type` will be ignored.
 * see https://github.com/phetsims/axon/issues/204 for more details.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
Emitter.createEmitterIO = parameterTypes => {

  const key = parameterTypes.map( paramToTypeName ).join( ',' );

  if ( !cache.hasOwnProperty( key ) ) {

    const ActionIOType = Action.createActionIO( parameterTypes );
    cache[ key ] = ObjectIO.createIOType( Emitter, `EmitterIO<${parameterTypes.map( paramToTypeName ).join( ', ' )}>`, {
      parentIOType: ActionIOType,
      documentation: 'Emits when an event occurs and calls added listeners.',
      events: [ 'emitted' ],
      parameterTypes: parameterTypes,
      methods: {
        addListener: {
          returnType: VoidIO,
          parameterTypes: [ FunctionIO( VoidIO, parameterTypes ) ],
          implementation: function( listener ) {
            this.phetioObject.addListener( listener );
          },
          documentation: 'Adds a listener which will be called when the emitter emits.'
        },
        emit: {
          returnType: VoidIO,
          parameterTypes: parameterTypes,

          // Match `Emitter.emit`'s dynamic number of arguments
          implementation: function() {
            this.phetioObject.emit.apply( this.phetioObject, arguments );
          },
          documentation: 'Emits a single event to all listeners.',
          invocableForReadOnlyElements: false
        }
      }
    } );
  }
  return cache[ key ];
};

axon.register( 'Emitter', Emitter );
export default Emitter;<commit_msg>Restore recursive check for events, see https://github.com/phetsims/phet-io/issues/1371<commit_after>// Copyright 2019-2020, University of Colorado Boulder

/**
 * Event & listener abstraction for a single "event" type. The type provides extra functionality beyond just notifying
 * listeners. It adds PhET-iO instrumentation capabilities as well as validation. For the lightest-weight, fastest
 * solution with the smallest memory footprint, see `TinyEmitter`.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Michael Kauzmann (PhET Interactive Simulations)
 */

import merge from '../../phet-core/js/merge.js';
import FunctionIO from '../../tandem/js/types/FunctionIO.js';
import ObjectIO from '../../tandem/js/types/ObjectIO.js';
import VoidIO from '../../tandem/js/types/VoidIO.js';
import Action from './Action.js';
import axon from './axon.js';
import TinyEmitter from './TinyEmitter.js';

class Emitter extends Action {

  /**
   * @param {Object} [options]
   */
  constructor( options ) {

    options = merge( {
      phetioOuterType: Emitter.createEmitterIO
    }, options );

    super( function() {
      assert && assert( self.tinyEmitter instanceof TinyEmitter,
        'Emitter should not emit until after its constructor has completed' );

      self.tinyEmitter.emit.apply( self.tinyEmitter, arguments );
    }, options );

    const self = this;

    // @private - provide Emitter functionality via composition
    this.tinyEmitter = new TinyEmitter();
  }

  /**
   * Emitter instances should not be calling Action.execute, instead see Emitter.emit().
   * See the second half of https://github.com/phetsims/axon/issues/243 for discussion.
   * @override
   * @public
   */
  execute() {
    assert && assert( false, 'This should not be called, use Emitter.emit() instead.' );
  }

  /**
   * Emit to notify listeners; implemented by executing the action of the parent class.
   * @public
   * @params {*}
   */
  emit() {
    super.execute.apply( this, arguments );
  }

  /**
   * Disposes an Emitter. All listeners are removed.
   * @public
   * @override
   */
  dispose() {
    this.tinyEmitter.dispose();
    super.dispose();
  }

  /**
   * Adds a listener which will be called during emit.
   * @param {function} listener
   * @public
   */
  addListener( listener ) {
    this.tinyEmitter.addListener( listener );
  }

  /**
   * Removes a listener
   * @param {function} listener
   * @public
   */
  removeListener( listener ) {
    this.tinyEmitter.removeListener( listener );
  }

  /**
   * Removes all the listeners
   * @public
   */
  removeAllListeners() {
    this.tinyEmitter.removeAllListeners();
  }

  /**
   * Checks whether a listener is registered with this Emitter
   * @param {function} listener
   * @returns {boolean}
   * @public
   */
  hasListener( listener ) {
    return this.tinyEmitter.hasListener( listener );
  }

  /**
   * Returns true if there are any listeners.
   * @returns {boolean}
   * @public
   */
  hasListeners() {
    return this.tinyEmitter.hasListeners();
  }

  /**
   * Returns the number of listeners.
   * @returns {number}
   * @public
   */
  getListenerCount() {
    return this.tinyEmitter.getListenerCount();
  }
}

const paramToTypeName = param => param.typeName;
const cache = {};

/**
 * IO Type for Emitter.
 *
 * Providing validators to instrumented Emitters:
 * Instrumented Emitters should have their `validators` for each argument passed via EmitterIO (the phetioType).
 * To provide validators, there are two methods. First, by default each TypeIO has its own
 * validator that will be used. So specifying an argument object like `{ type: NumberIO }` will automatically use
 * `NumberIO.validator` as the validator. This can be overridden with the `validator` key (second option), like
 * { type: NumberIO, validator: { isValidValue: v=> typeof v === 'number' &&  v < 5 } }`
 * NOTE: currently the implementation is either/or, if a validator is provided via the `validator` key, the validator
 * from the `type` will be ignored.
 * see https://github.com/phetsims/axon/issues/204 for more details.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Michael Kauzmann (PhET Interactive Simulations)
 * @author Andrew Adare (PhET Interactive Simulations)
 */
Emitter.createEmitterIO = parameterTypes => {

  const key = parameterTypes.map( paramToTypeName ).join( ',' );

  if ( !cache.hasOwnProperty( key ) ) {

    const ActionIOType = Action.createActionIO( parameterTypes );
    cache[ key ] = ObjectIO.createIOType( Emitter, `EmitterIO<${parameterTypes.map( paramToTypeName ).join( ', ' )}>`, {
      parentIOType: ActionIOType,
      documentation: 'Emits when an event occurs and calls added listeners.',
      parameterTypes: parameterTypes,
      methods: {
        addListener: {
          returnType: VoidIO,
          parameterTypes: [ FunctionIO( VoidIO, parameterTypes ) ],
          implementation: function( listener ) {
            this.phetioObject.addListener( listener );
          },
          documentation: 'Adds a listener which will be called when the emitter emits.'
        },
        emit: {
          returnType: VoidIO,
          parameterTypes: parameterTypes,

          // Match `Emitter.emit`'s dynamic number of arguments
          implementation: function() {
            this.phetioObject.emit.apply( this.phetioObject, arguments );
          },
          documentation: 'Emits a single event to all listeners.',
          invocableForReadOnlyElements: false
        }
      }
    } );
  }
  return cache[ key ];
};

axon.register( 'Emitter', Emitter );
export default Emitter;<|endoftext|>


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

/**
 * Horizontal slider.
 *
 * Moved from beers-law-lab/EvaporationSlider on 9/15/2013
 * see https://github.com/phetsims/sun/issues/9
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var Dimension2 = require( 'DOT/Dimension2' );
  var inherit = require( 'PHET_CORE/inherit' );
  var LinearFunction = require( 'DOT/LinearFunction' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Path = require( 'SCENERY/nodes/Path' );
  var Property = require( 'AXON/Property' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var Shape = require( 'KITE/Shape' );
  var SimpleDragHandler = require( 'SCENERY/input/SimpleDragHandler' );
  var ButtonListener = require( 'SCENERY/input/ButtonListener' );
  var Input = require( 'SCENERY/input/Input' );
  var Util = require( 'DOT/Util' );

  /**
   * @param {Property.<number>} valueProperty
   * @param { {min:number, max:number} } range
   * @param {Object} [options]
   * @constructor
   */
  function HSlider( valueProperty, range, options ) {

    var thisSlider = this;
    Node.call( thisSlider );

    options = _.extend( {
      // track
      trackSize: new Dimension2( 100, 5 ),
      trackFill: 'white',
      trackStroke: 'black',
      trackLineWidth: 1,
      // {Node} optional thumb, replaces the default. Client is responsible for highlighting and disabling. Centered in the track.
      thumbNode: null,
      // default thumb (ignored if thumbNode is provided)
      thumbSize: new Dimension2( 22, 45 ),
      thumbFillEnabled: 'rgb(50,145,184)',
      thumbFillHighlighted: 'rgb(71,207,255)',
      thumbFillDisabled: '#F0F0F0',
      thumbStroke: 'black',
      thumbLineWidth: 1,
      thumbCenterLineStroke: 'white',
      // ticks
      tickLabelSpacing: 6,
      majorTickLength: 25,
      majorTickStroke: 'black',
      majorTickLineWidth: 1,
      minorTickLength: 10,
      minorTickStroke: 'black',
      minorTickLineWidth: 1,
      // other
      cursor: 'pointer',
      enabledProperty: new Property( true ),
      startDrag: function() {}, // called when a drag sequence starts
      endDrag: function() {}, // called when a drag sequence ends
    }, options );
    this.options = options; // @private TODO save only the options that are needed by prototype functions

    // @private ticks are added to this parent, so they are behind knob
    thisSlider.ticksParent = new Node();
    thisSlider.addChild( thisSlider.ticksParent );

    // @private mapping between value and track position
    thisSlider.valueToPosition = new LinearFunction( range.min, range.max, 0, options.trackSize.width, true /* clamp */ );

    // @private track
    thisSlider.track = new Rectangle( 0, 0, options.trackSize.width, options.trackSize.height,
      { fill: options.trackFill, stroke: options.trackStroke, lineWidth: options.trackLineWidth } );
    thisSlider.addChild( thisSlider.track );

    // click in the track to change the value, continue dragging if desired
    var trackHandler = new SimpleDragHandler( {
      handleTrackEvent: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          var transform = trail.subtrailTo( thisSlider ).getTransform();
          var x = transform.inversePosition2( event.pointer.point ).x;
          valueProperty.set( thisSlider.valueToPosition.inverse( x ) );
        }
      },
      start: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          options.startDrag();
        }
        this.handleTrackEvent( event, trail );
      },
      drag: function( event, trail ) {
        this.handleTrackEvent( event, trail );
      },
      end: function() {
        if ( options.enabledProperty.get() ) {
          options.endDrag();
        }
      }
    } );
    thisSlider.track.addInputListener( trackHandler );

    // thumb
    var thumb = options.thumbNode || new ThumbNode( options );

    // Make the thumb focusable for keyboard accessibility
    thumb.focusable = true;

    thisSlider.thumb = thumb; // must be disposed of
    thumb.centerY = thisSlider.track.centerY;
    thisSlider.addChild( thumb );

    // Keyboard accessibility
    thumb.addInputListener( {
      keydown: function( event, trail ) {
        var keyCode = event.domEvent.keyCode;
        var delta = keyCode === Input.KEY_LEFT_ARROW || keyCode === Input.KEY_DOWN_ARROW ? -1 :
                    keyCode === Input.KEY_RIGHT_ARROW || keyCode === Input.KEY_UP_ARROW ? +1 :
                    0;
        valueProperty.set( Util.clamp( valueProperty.get() + (range.max - range.min) * 0.1 * delta, range.min, range.max ) );
      }
    } );

    // thumb touch area
    if ( !options.thumbNode ) {
      var dx = 0.5 * thumb.width;
      var dy = 0.25 * thumb.height;
      thumb.touchArea = Shape.rectangle( ( -thumb.width / 2 ) - dx, ( -thumb.height / 2 ) - dy, thumb.width + dx + dx, thumb.height + dy + dy );
    }

    // update value when thumb is dragged
    var thumbHandler = new SimpleDragHandler( {

      // x-offset between initial click and thumb's origin
      clickXOffset: 0,

      allowTouchSnag: true,

      start: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          thisSlider.trigger1( 'startedCallbacksForDragStarted', valueProperty.get() );
          options.startDrag();

          var transform = trail.subtrailTo( thisSlider ).getTransform();
          this.clickXOffset = transform.inversePosition2( event.pointer.point ).x - thumb.x;

          thisSlider.trigger1( 'endedCallbacksForDragStarted', valueProperty.get() );
        }
      },

      drag: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          thisSlider.trigger1( 'startedCallbacksForDragged', valueProperty.get() );
          var transform = trail.subtrailTo( thisSlider ).getTransform(); // we only want the transform to our parent
          var x = transform.inversePosition2( event.pointer.point ).x - this.clickXOffset;
          var newValue = thisSlider.valueToPosition.inverse( x );

          valueProperty.set( newValue );

          thisSlider.trigger1( 'endedCallbacksForDragged', valueProperty.get() );
        }
      },

      end: function() {
        if ( options.enabledProperty.get() ) {
          thisSlider.trigger1( 'startedCallbacksForDragEnded', valueProperty.get() );
          options.endDrag();
          thisSlider.trigger1( 'endedCallbacksForDragEnded', valueProperty.get() );
        }
      }
    } );
    thumb.addInputListener( thumbHandler );

    // @private enable/disable
    thisSlider.enabledObserver = function( enabled ) {
      thisSlider.cursor = options.enabledProperty.get() ? options.cursor : 'default';
      if ( !enabled ) {
        if ( thumbHandler.dragging ) { thumbHandler.endDrag(); }
        if ( trackHandler.dragging ) { trackHandler.endDrag(); }
      }
    };
    thisSlider.enabledProperty = options.enabledProperty; // @private
    thisSlider.enabledProperty.link( thisSlider.enabledObserver ); // must be unlinked in dispose

    // @private update thumb location when value changes
    thisSlider.valueObserver = function( value ) {
      thumb.centerX = thisSlider.valueToPosition( value );
    };
    thisSlider.valueProperty = valueProperty; // @private
    thisSlider.valueProperty.link( thisSlider.valueObserver ); // must be unlinked in dispose

    thisSlider.mutate( options );
  }

  inherit( Node, HSlider, {

    // Ensures that this object is eligible for GC.
    dispose: function() {
      this.thumb.dispose();
      this.thumb = null;
      this.valueProperty.unlink( this.valueObserver );
      this.enabledProperty.unlink( this.enabledObserver );
    },

    /**
     * Adds a major tick mark.
     * @param {number} value
     * @param {Node} [label] optional
     */
    addMajorTick: function( value, label ) {
      this.addTick( value, label, this.options.majorTickLength, this.options.majorTickStroke, this.options.majorTickLineWidth );
    },

    /**
     * Adds a minor tick mark.
     * @param {number} value
     * @param {Node} [label] optional
     */
    addMinorTick: function( value, label ) {
      this.addTick( value, label, this.options.minorTickLength, this.options.minorTickStroke, this.options.minorTickLineWidth );
    },

    /*
     * Adds a tick mark above the track.
     * @param {number} value
     * @param {Node} [label] optional
     * @param {number} length
     * @param {number} stroke
     * @param {number} lineWidth
     * @private
     */
    addTick: function( value, label, length, stroke, lineWidth ) {
      var labelX = this.valueToPosition( value );
      // ticks
      var tick = new Path( new Shape()
          .moveTo( labelX, this.track.top )
          .lineTo( labelX, this.track.top - length ),
        { stroke: stroke, lineWidth: lineWidth } );
      this.ticksParent.addChild( tick );
      // label
      if ( label ) {
        this.ticksParent.addChild( label );
        label.centerX = tick.centerX;
        label.bottom = tick.top - this.options.tickLabelSpacing;
      }
    }
  } );

  /**
   * Default thumb, a rectangle with a vertical white line down the center
   * @param {Object} [options] see HSlider constructor
   * @constructor
   */
  function ThumbNode( options ) {

    assert && assert( options ); // these are options provided to HSlider, not optional for this inner type

    var thisNode = this;

    // rectangle
    var arcWidth = 0.25 * options.thumbSize.width;
    Rectangle.call( thisNode,
      -options.thumbSize.width / 2, -options.thumbSize.height / 2,
      options.thumbSize.width, options.thumbSize.height,
      arcWidth, arcWidth,
      {
        fill: options.enabledProperty.get() ? options.thumbFillEnabled : options.thumbFillDisabled,
        stroke: options.thumbStroke,
        lineWidth: options.thumbLineWidth
      } );

    // vertical line down the center
    var centerLineYMargin = 3;
    thisNode.addChild( new Path( Shape.lineSegment(
        0, -( options.thumbSize.height / 2 ) + centerLineYMargin,
        0, ( options.thumbSize.height / 2 ) - centerLineYMargin ),
      { stroke: options.thumbCenterLineStroke } ) );

    // highlight thumb on pointer over
    thisNode.addInputListener( new ButtonListener( {
      over: function( event ) {
        if ( options.enabledProperty.get() ) { thisNode.fill = options.thumbFillHighlighted; }
      },
      up: function( event ) {
        if ( options.enabledProperty.get() ) { thisNode.fill = options.thumbFillEnabled; }
      }
    } ) );

    // @private enable/disable the look of the thumb
    this.enabledObserver = function( enabled ) {
      thisNode.fill = enabled ? options.thumbFillEnabled : options.thumbFillDisabled;
    };
    this.enabledProperty = options.enabledProperty; // @private
    this.enabledProperty.link( this.enabledObserver ); // must be unlinked in dispose
  }

  inherit( Rectangle, ThumbNode, {

    // Ensures that this object is eligible for GC.
    dispose: function() {
      this.enabledProperty.unlink( this.enabledObserver );
    }
  } );

  return HSlider;
} );<commit_msg>delete stray comma<commit_after>// Copyright 2002-2013, University of Colorado Boulder

/**
 * Horizontal slider.
 *
 * Moved from beers-law-lab/EvaporationSlider on 9/15/2013
 * see https://github.com/phetsims/sun/issues/9
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var Dimension2 = require( 'DOT/Dimension2' );
  var inherit = require( 'PHET_CORE/inherit' );
  var LinearFunction = require( 'DOT/LinearFunction' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Path = require( 'SCENERY/nodes/Path' );
  var Property = require( 'AXON/Property' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var Shape = require( 'KITE/Shape' );
  var SimpleDragHandler = require( 'SCENERY/input/SimpleDragHandler' );
  var ButtonListener = require( 'SCENERY/input/ButtonListener' );
  var Input = require( 'SCENERY/input/Input' );
  var Util = require( 'DOT/Util' );

  /**
   * @param {Property.<number>} valueProperty
   * @param { {min:number, max:number} } range
   * @param {Object} [options]
   * @constructor
   */
  function HSlider( valueProperty, range, options ) {

    var thisSlider = this;
    Node.call( thisSlider );

    options = _.extend( {
      // track
      trackSize: new Dimension2( 100, 5 ),
      trackFill: 'white',
      trackStroke: 'black',
      trackLineWidth: 1,
      // {Node} optional thumb, replaces the default. Client is responsible for highlighting and disabling. Centered in the track.
      thumbNode: null,
      // default thumb (ignored if thumbNode is provided)
      thumbSize: new Dimension2( 22, 45 ),
      thumbFillEnabled: 'rgb(50,145,184)',
      thumbFillHighlighted: 'rgb(71,207,255)',
      thumbFillDisabled: '#F0F0F0',
      thumbStroke: 'black',
      thumbLineWidth: 1,
      thumbCenterLineStroke: 'white',
      // ticks
      tickLabelSpacing: 6,
      majorTickLength: 25,
      majorTickStroke: 'black',
      majorTickLineWidth: 1,
      minorTickLength: 10,
      minorTickStroke: 'black',
      minorTickLineWidth: 1,
      // other
      cursor: 'pointer',
      enabledProperty: new Property( true ),
      startDrag: function() {}, // called when a drag sequence starts
      endDrag: function() {} // called when a drag sequence ends
    }, options );
    this.options = options; // @private TODO save only the options that are needed by prototype functions

    // @private ticks are added to this parent, so they are behind knob
    thisSlider.ticksParent = new Node();
    thisSlider.addChild( thisSlider.ticksParent );

    // @private mapping between value and track position
    thisSlider.valueToPosition = new LinearFunction( range.min, range.max, 0, options.trackSize.width, true /* clamp */ );

    // @private track
    thisSlider.track = new Rectangle( 0, 0, options.trackSize.width, options.trackSize.height,
      { fill: options.trackFill, stroke: options.trackStroke, lineWidth: options.trackLineWidth } );
    thisSlider.addChild( thisSlider.track );

    // click in the track to change the value, continue dragging if desired
    var trackHandler = new SimpleDragHandler( {
      handleTrackEvent: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          var transform = trail.subtrailTo( thisSlider ).getTransform();
          var x = transform.inversePosition2( event.pointer.point ).x;
          valueProperty.set( thisSlider.valueToPosition.inverse( x ) );
        }
      },
      start: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          options.startDrag();
        }
        this.handleTrackEvent( event, trail );
      },
      drag: function( event, trail ) {
        this.handleTrackEvent( event, trail );
      },
      end: function() {
        if ( options.enabledProperty.get() ) {
          options.endDrag();
        }
      }
    } );
    thisSlider.track.addInputListener( trackHandler );

    // thumb
    var thumb = options.thumbNode || new ThumbNode( options );

    // Make the thumb focusable for keyboard accessibility
    thumb.focusable = true;

    thisSlider.thumb = thumb; // must be disposed of
    thumb.centerY = thisSlider.track.centerY;
    thisSlider.addChild( thumb );

    // Keyboard accessibility
    thumb.addInputListener( {
      keydown: function( event, trail ) {
        var keyCode = event.domEvent.keyCode;
        var delta = keyCode === Input.KEY_LEFT_ARROW || keyCode === Input.KEY_DOWN_ARROW ? -1 :
                    keyCode === Input.KEY_RIGHT_ARROW || keyCode === Input.KEY_UP_ARROW ? +1 :
                    0;
        valueProperty.set( Util.clamp( valueProperty.get() + (range.max - range.min) * 0.1 * delta, range.min, range.max ) );
      }
    } );

    // thumb touch area
    if ( !options.thumbNode ) {
      var dx = 0.5 * thumb.width;
      var dy = 0.25 * thumb.height;
      thumb.touchArea = Shape.rectangle( ( -thumb.width / 2 ) - dx, ( -thumb.height / 2 ) - dy, thumb.width + dx + dx, thumb.height + dy + dy );
    }

    // update value when thumb is dragged
    var thumbHandler = new SimpleDragHandler( {

      // x-offset between initial click and thumb's origin
      clickXOffset: 0,

      allowTouchSnag: true,

      start: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          thisSlider.trigger1( 'startedCallbacksForDragStarted', valueProperty.get() );
          options.startDrag();

          var transform = trail.subtrailTo( thisSlider ).getTransform();
          this.clickXOffset = transform.inversePosition2( event.pointer.point ).x - thumb.x;

          thisSlider.trigger1( 'endedCallbacksForDragStarted', valueProperty.get() );
        }
      },

      drag: function( event, trail ) {
        if ( options.enabledProperty.get() ) {
          thisSlider.trigger1( 'startedCallbacksForDragged', valueProperty.get() );
          var transform = trail.subtrailTo( thisSlider ).getTransform(); // we only want the transform to our parent
          var x = transform.inversePosition2( event.pointer.point ).x - this.clickXOffset;
          var newValue = thisSlider.valueToPosition.inverse( x );

          valueProperty.set( newValue );

          thisSlider.trigger1( 'endedCallbacksForDragged', valueProperty.get() );
        }
      },

      end: function() {
        if ( options.enabledProperty.get() ) {
          thisSlider.trigger1( 'startedCallbacksForDragEnded', valueProperty.get() );
          options.endDrag();
          thisSlider.trigger1( 'endedCallbacksForDragEnded', valueProperty.get() );
        }
      }
    } );
    thumb.addInputListener( thumbHandler );

    // @private enable/disable
    thisSlider.enabledObserver = function( enabled ) {
      thisSlider.cursor = options.enabledProperty.get() ? options.cursor : 'default';
      if ( !enabled ) {
        if ( thumbHandler.dragging ) { thumbHandler.endDrag(); }
        if ( trackHandler.dragging ) { trackHandler.endDrag(); }
      }
    };
    thisSlider.enabledProperty = options.enabledProperty; // @private
    thisSlider.enabledProperty.link( thisSlider.enabledObserver ); // must be unlinked in dispose

    // @private update thumb location when value changes
    thisSlider.valueObserver = function( value ) {
      thumb.centerX = thisSlider.valueToPosition( value );
    };
    thisSlider.valueProperty = valueProperty; // @private
    thisSlider.valueProperty.link( thisSlider.valueObserver ); // must be unlinked in dispose

    thisSlider.mutate( options );
  }

  inherit( Node, HSlider, {

    // Ensures that this object is eligible for GC.
    dispose: function() {
      this.thumb.dispose();
      this.thumb = null;
      this.valueProperty.unlink( this.valueObserver );
      this.enabledProperty.unlink( this.enabledObserver );
    },

    /**
     * Adds a major tick mark.
     * @param {number} value
     * @param {Node} [label] optional
     */
    addMajorTick: function( value, label ) {
      this.addTick( value, label, this.options.majorTickLength, this.options.majorTickStroke, this.options.majorTickLineWidth );
    },

    /**
     * Adds a minor tick mark.
     * @param {number} value
     * @param {Node} [label] optional
     */
    addMinorTick: function( value, label ) {
      this.addTick( value, label, this.options.minorTickLength, this.options.minorTickStroke, this.options.minorTickLineWidth );
    },

    /*
     * Adds a tick mark above the track.
     * @param {number} value
     * @param {Node} [label] optional
     * @param {number} length
     * @param {number} stroke
     * @param {number} lineWidth
     * @private
     */
    addTick: function( value, label, length, stroke, lineWidth ) {
      var labelX = this.valueToPosition( value );
      // ticks
      var tick = new Path( new Shape()
          .moveTo( labelX, this.track.top )
          .lineTo( labelX, this.track.top - length ),
        { stroke: stroke, lineWidth: lineWidth } );
      this.ticksParent.addChild( tick );
      // label
      if ( label ) {
        this.ticksParent.addChild( label );
        label.centerX = tick.centerX;
        label.bottom = tick.top - this.options.tickLabelSpacing;
      }
    }
  } );

  /**
   * Default thumb, a rectangle with a vertical white line down the center
   * @param {Object} [options] see HSlider constructor
   * @constructor
   */
  function ThumbNode( options ) {

    assert && assert( options ); // these are options provided to HSlider, not optional for this inner type

    var thisNode = this;

    // rectangle
    var arcWidth = 0.25 * options.thumbSize.width;
    Rectangle.call( thisNode,
      -options.thumbSize.width / 2, -options.thumbSize.height / 2,
      options.thumbSize.width, options.thumbSize.height,
      arcWidth, arcWidth,
      {
        fill: options.enabledProperty.get() ? options.thumbFillEnabled : options.thumbFillDisabled,
        stroke: options.thumbStroke,
        lineWidth: options.thumbLineWidth
      } );

    // vertical line down the center
    var centerLineYMargin = 3;
    thisNode.addChild( new Path( Shape.lineSegment(
        0, -( options.thumbSize.height / 2 ) + centerLineYMargin,
        0, ( options.thumbSize.height / 2 ) - centerLineYMargin ),
      { stroke: options.thumbCenterLineStroke } ) );

    // highlight thumb on pointer over
    thisNode.addInputListener( new ButtonListener( {
      over: function( event ) {
        if ( options.enabledProperty.get() ) { thisNode.fill = options.thumbFillHighlighted; }
      },
      up: function( event ) {
        if ( options.enabledProperty.get() ) { thisNode.fill = options.thumbFillEnabled; }
      }
    } ) );

    // @private enable/disable the look of the thumb
    this.enabledObserver = function( enabled ) {
      thisNode.fill = enabled ? options.thumbFillEnabled : options.thumbFillDisabled;
    };
    this.enabledProperty = options.enabledProperty; // @private
    this.enabledProperty.link( this.enabledObserver ); // must be unlinked in dispose
  }

  inherit( Rectangle, ThumbNode, {

    // Ensures that this object is eligible for GC.
    dispose: function() {
      this.enabledProperty.unlink( this.enabledObserver );
    }
  } );

  return HSlider;
} );<|endoftext|>


<commit_before>'use strict';

export default class ProductsService {

    static get $inject(){
        return ['$http', 'API_URL'];
    }

    constructor($http,API_URL) {
        this.$http = $http;
        this.resourceUrl = `${ API_URL }/products/`;
        this.extraUrl = 'seller/';

    }

    static get name(){
        return 'productsService';
    }

    list() {

        let url = this.resourceUrl;
        return this.$http.get(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);

            });

        });

    }

    get(id) {
        let url = `${ this.resourceUrl }${ id }`;
        return this.$http.get(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);
            });

        })
    }

    create(product) {
        let url = this.resourceUrl;
        return this.$http.post(url,product).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);
            });

        })
    }

    delete(id) {
        let url = `${ this.resourceUrl }${ id }`;
        return this.$http.delete(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.status);
            });

        })
    }

    update(product) {

        let url = `${ this.resourceUrl }${ product['_id'] }`;
        return this.$http.put(url,product).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);
            });

        })
    }

    listProducts(id) {
        let url = `${ this.resourceUrl }${ this.extraUrl }${ id }`;
        return this.$http.get(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);

            });

        });

    }

}
<commit_msg>Securing the web application - Users will not be able to access product listing page of other users<commit_after>'use strict';

export default class ProductsService {

    static get $inject(){
        return ['$http', 'API_URL', 'UserService', '$state'];
    }

    constructor($http,API_URL,UserService,$state) {
        this.$http = $http;
        this.resourceUrl = `${ API_URL }/products/`;
        this.extraUrl = 'seller/';
        this.UserService = UserService;
        this.$state = $state;

    }

    static get name(){
        return 'productsService';
    }

    list() {

        let url = this.resourceUrl;
        return this.$http.get(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);

            });

        });

    }

    get(id) {
        let url = `${ this.resourceUrl }${ id }`;
        return this.$http.get(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);
            });

        })
    }

    create(product) {
        let url = this.resourceUrl;
        return this.$http.post(url,product).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);
            });

        })
    }

    delete(id) {
        let url = `${ this.resourceUrl }${ id }`;
        return this.$http.delete(url).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.status);
            });

        })
    }

    update(product) {
        let url = `${ this.resourceUrl }${ product['_id'] }`;
        return this.$http.put(url,product).then(responce => {

            return new Promise((resolve, reject) => {
                resolve(responce.data);
            });

        })
    }

    listProducts(id) {
        // make sure that user is not able to see product listing of another user
        let requestingUser = this.UserService.getCurrentUser();
        if (requestingUser['_id'] === id) {
            let url = `${ this.resourceUrl }${ this.extraUrl }${ id }`;
            return this.$http.get(url).then(responce => {

                return new Promise((resolve, reject) => {
                    resolve(responce.data);

                });
            });
        } else {
            this.$state.go('home',{});
        }

    }

}
<|endoftext|>


<commit_before>/**
 * Class Sliders
 */
Humble( function () {

    var Sliders = function (node, model) {

        this.model      = model;
        this.node       = node;
        this.sliders    = {};

        this.render();
    }

    Sliders.prototype = {

        render : function () {

            var dimensions  = Humble.Config.DVZ.budget.dimensions,
                sliders     = {},
                node        = this.node;

            _.each(dimensions, function (name, key) {
                var slider = this._renderSlider(name);
                node.append(slider);
                slider.data('key', key);
                sliders[key] = slider;
            }, this);

            this._sliders = sliders;
        },

        _renderSlider : function (name) {

            var slider = $('

'),
                widget = $('

'),
                value  = 0,
                title  = name,
                config;

            slider.append('
$'+value+'
');
            slider.append('
'+title+'
');
            slider.append(widget);

            config = {
                max : 1000,
                value : value
            };

            widget.slider(config);

            return slider;
        },

        bind : function () {
            this.node.delegate('.slider', 'slide', {this : this}, this._onSlide);
        },

        update : function () {

            var sliders = this._sliders;

            var items   = this.model.getItems(),
                node    = this.node;

            _.each(sliders, function (slider, key) {

                var value = items[key]['mycosti'];

                slider = slider.find('.ui-slider');
                value  = this._translate(value);

                $(slider).slider('value', [value]);

            }, this);

            this.bind();
        },

        _onSlide : function (e, ui) {

            var key     = $(this).data('key'),
                sliders = e.data.this;

            $(this).find('.mycosti').html('$'+ui.value);
            sliders.model.set(key, 'mycosti', ui.value);
        },

        /**
         * Slider Value
         *
         * Slider goes from 0 to 100
         */
        _translate : function (value) {

            // Income
            var max = 50000;

            value = (value / max) * 1000;

            return value;
        }
    }

    Humble.Sliders = Sliders;
});
<commit_msg>Construct title and value divs independently.  Added updates for Slider and SliderLabel (these should be factored into Slider class).  Fix so that slider label is updated on 'update'.<commit_after>/**
 * Class Sliders
 */
Humble( function () {

    var Sliders = function (node, model) {

        this.model      = model;
        this.node       = node;
        this.sliders    = {};

        this.render();
    }

    Sliders.prototype = {

        render : function () {

            var dimensions  = Humble.Config.DVZ.budget.dimensions,
                sliders     = {},
                node        = this.node;

            _.each(dimensions, function (name, key) {
                var slider = this._renderSlider(name);
                node.append(slider);
                slider.data('key', key);
                sliders[key] = slider;
            }, this);

            this._sliders = sliders;
        },

        _renderSlider : function (name) {

            var value  = 0,
                label  = $('
$'+value+'
'),
                slider = $('

'),
                widget = $('

'),
                title  = $('
'+name+'
'),
                config;

            slider.append(label);
            slider.append(title);
            slider.append(widget);

            config = {
                max : 1000,
                value : value
            };

            widget.slider(config);

            return slider;
        },

        bind : function () {
            this.node.delegate('.slider', 'slide', {this : this}, this._onSlide);
        },

        update : function () {

            var sliders = this._sliders;

            var items   = this.model.getItems(),
                node    = this.node;

            _.each(sliders, function (slider, key) {
                var value = items[key]['mycosti'];
                this._updateSlider(slider, value);
            }, this);

            this.bind();
        },

        _onSlide : function (e, ui) {

            var key     = $(this).data('key'),
                label   = $(this).find('.mycosti');
                sliders = e.data.this;

            sliders.model.set(key, 'mycosti', ui.value);
            this._updateSliderLabel(label, value);
        },

        _updateSlider : function (slider, value) {

            var widget = slider.find('.ui-slider'),
                label  = slider.find('.mycosti');

            value  = this._translate(value);

            widget.slider('value', [value]);
            this._updateSliderLabel(label, value);
        },

        _updateSliderLabel : function (label, value) {
            label.html('$'+value);
        },

        /**
         * Slider Value
         *
         * Slider goes from 0 to 100
         */
        _translate : function (value) {

            // Income
            var max = 50000;

            value = (value / max) * 1000;

            return value;
        }
    }

    Humble.Sliders = Sliders;
});
<|endoftext|>


<commit_before>"use strict";

angular.module("angular-mobile-docs")
    .factory("FetchService", function ($http, $q, LocalStorageCache, baseUrl) {

        var getVersionList = function () {
            /*
             TODO: LocalStorage for already downloaded files.
             But also should fetch if net is available
              */
            return $http.get(
                baseUrl
                    + "versions/"
                    + "index.json"
                , {cache: true}//{cache: LocalStorageCache}
            );
        }

        var getFileList = function (version) {
            return $http.get(
                baseUrl
                    + "versions/"
                    + version
                    + ".api.json"
                , {cache: LocalStorageCache}
            );
        }

        var getPartial = function (version, name) {
            return $http.get(
                baseUrl
                    + "code/"
                    + version
                    + "/docs/partials/api/" + name
                , {cache: LocalStorageCache});
        }

        var getAllPartials = function (version) {
            var promises = [];
            getFileList(version)
                .then(function (fileNameList) {
                    console.log(fileNameList);
                    angular.forEach(fileNameList.data, function (fileName) {
                        promises.push(getPartial(version, fileName));
                    })
                });

            return $q.all(promises);
        }

        return {
            getVersionList: function () {
                return getVersionList();
            },
            getFileList   : function (version) {
                return getFileList(version);
            },
            getPartial    : function (version, name) {
                return getPartial(version, name);
            },
            getAllPartials: function (version) {
                return getAllPartials(version);
            }

        };

    });<commit_msg>Fix: Support older devices with session cache<commit_after>"use strict";

angular.module("angular-mobile-docs")
    .factory("FetchService", function ($http, $q, LocalStorageCache, baseUrl) {

        var getVersionList = function () {
            /*
             TODO: LocalStorage for already downloaded files.
             But also should fetch if net is available
              */
            return $http.get(
                baseUrl
                    + "versions/"
                    + "index.json"
                , {cache: true}//{cache: LocalStorageCache}
            );
        }

        var getFileList = function (version) {
            return $http.get(
                baseUrl
                    + "versions/"
                    + version
                    + ".api.json"
                , {cache: (localStorage)?LocalStorageCache:true}
            );
        }

        var getPartial = function (version, name) {
            return $http.get(
                baseUrl
                    + "code/"
                    + version
                    + "/docs/partials/api/" + name
                , {cache: (localStorage)?LocalStorageCache:true});
        }

        var getAllPartials = function (version) {
            var promises = [];
            getFileList(version)
                .then(function (fileNameList) {
                    console.log(fileNameList);
                    angular.forEach(fileNameList.data, function (fileName) {
                        promises.push(getPartial(version, fileName));
                    })
                });

            return $q.all(promises);
        }

        return {
            getVersionList: function () {
                return getVersionList();
            },
            getFileList   : function (version) {
                return getFileList(version);
            },
            getPartial    : function (version, name) {
                return getPartial(version, name);
            },
            getAllPartials: function (version) {
                return getAllPartials(version);
            }

        };

    });<|endoftext|>


<commit_before>import React, { Component } from 'react';

// Utils
import * as _ from 'lodash';

import VisibilitySensor from 'react-visibility-sensor';

// App
export default class ISeeYou extends Component {
	constructor(props) {
		super(props);

		this.state = {
			visible: false
		}
	}

	handleInview(isVisible) {
		window.alert('Change!');
		if (isVisible == true) {
			this.setState({
				visible: true
			});
		}
	}

	render() {
      return (
		<VisibilitySensor scrollCheck scrollDelay={50} onChange={this.handleInview.bind(this)} partialVisibility={true}>

				{this.props.children}

		</VisibilitySensor>
      );
  }
};
<commit_msg>In view<commit_after>import React, { Component } from 'react';

// Utils
import * as _ from 'lodash';

import VisibilitySensor from 'react-visibility-sensor';

// App
export default class ISeeYou extends Component {
	constructor(props) {
		super(props);

		this.state = {
			visible: false
		}
	}

	handleInview(isVisible) {
		if (isVisible == true) {
			this.setState({
				visible: true
			});
		}
	}

	render() {
      return (
		<VisibilitySensor scrollCheck={true} scrollDelay={50} onChange={this.handleInview.bind(this)} partialVisibility={true}>

				{this.props.children}

		</VisibilitySensor>
      );
  }
};
<|endoftext|>