<commit_before>/**
 * jQuery Bar Rating Plugin v1.0.5
 *
 * http://github.com/antennaio/jquery-bar-rating
 *
 * Copyright (c) 2012-2014 Kazik Pietruszewski
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
(function ($) {
    var BarRating, root;

    root = typeof window !== "undefined" && window !== null ? window : global;

    root.BarRating = BarRating = (function () {

        function BarRating() {
            this.show = function () {
                var $elem = this.$elem,
                    $widget,
                    $all,
                    userOptions = this.options,
                    nextAllorPreviousAll,
                    initialOption;

                // run only once
                if (!$elem.data('barrating')) {

                    if (userOptions.initialRating) {
                        initialOption = $('option[value="' + userOptions.initialRating  + '"]', $elem);
                    } else {
                        initialOption = $('option:selected', $elem);
                    }

                    $elem.data('barrating', {

                        // initial rating based on the OPTION value
                        currentRatingValue:initialOption.val(),
                        currentRatingText:initialOption.text(),

                        // rating will be restored by calling destroy method
                        originalRatingValue:initialOption.val(),
                        originalRatingText:initialOption.text()

                    });

                    $widget = $('<div />', { 'class':'br-widget' }).insertAfter($elem);

                    // create A elements that will replace OPTIONs
                    $elem.find('option').each(function () {
                        var val, text, $a, $span;

                        val = $(this).val();

                        // create ratings - but only if val is defined
                        if (val) {
                            text = $(this).text();
                            $a = $('<a />', { href:'#', 'data-rating-value':val, 'data-rating-text':text });
                            $span = $('<span />', { text:(userOptions.showValues) ? text : '' });

                            $widget.append($a.append($span));
                        }

                    });

                    // append .br-current-rating div to the widget
                    if (userOptions.showSelectedRating) {
                        $widget.append($('<div />', { text:'', 'class':'br-current-rating' }));
                    }

                    // first OPTION empty - allow deselecting of ratings
                    $elem.data('barrating').deselectable = (!$elem.find('option:first').val()) ? true : false;

                    // use different jQuery function depending on the 'reverse' setting
                    if (userOptions.reverse) {
                        nextAllorPreviousAll = 'nextAll';
                    } else {
                        nextAllorPreviousAll = 'prevAll';
                    }

                    // additional classes for the widget
                    if (userOptions.reverse) {
                        $widget.addClass('br-reverse');
                    }

                    if (userOptions.readonly) {
                        $widget.addClass('br-readonly');
                    }

                    // rating change event
                    $widget.on('ratingchange',
                        function (event, value, text) {

                            // value or text undefined?
                            value = value ? value : $elem.data('barrating').currentRatingValue;
                            text = text ? text : $elem.data('barrating').currentRatingText;

                            // change selected OPTION in the select box (now hidden)
                            $elem.find('option[value="' + value + '"]').prop('selected', true);

                            $elem.change();

                            // update .br-current-rating div
                            if (userOptions.showSelectedRating) {
                                $(this).find('.br-current-rating').text(text);
                            }

                        }).trigger('ratingchange');

                    // update rating event
                    $widget.on('ratingstyle',
                        function (event) {
                            $widget.find('a').removeClass('br-selected br-current');

                            // add classes
                            $(this).find('a[data-rating-value="' + $elem.data('barrating').currentRatingValue + '"]')
                                .addClass('br-selected br-current')[nextAllorPreviousAll]()
                                .addClass('br-selected');

                        }).trigger('ratingstyle');

                    $all = $widget.find('a');

                    // fast clicks
                    $all.on('touchstart', function (event) {
                        event.preventDefault();
                        event.stopPropagation();

                        $(this).click();
                    });

                    // do not react to click events if rating is read-only
                    if (userOptions.readonly) {
                        $all.on('click', function (event) {
                            event.preventDefault();
                        });
                    }

                    // add interactions
                    if (!userOptions.readonly) {

                        $all.on('click', function (event) {
                            var $a = $(this),
                                value,
                                text;

                            event.preventDefault();

                            $all.removeClass('br-active br-selected');
                            $a.addClass('br-selected')[nextAllorPreviousAll]()
                                .addClass('br-selected');

                            value = $a.attr('data-rating-value');
                            text = $a.attr('data-rating-text');

                            // is current and deselectable?
                            if ($a.hasClass('br-current') && $elem.data('barrating').deselectable) {
                                $a.removeClass('br-selected br-current')[nextAllorPreviousAll]()
                                    .removeClass('br-selected br-current');
                                value = '', text = '';
                            } else {
                                $all.removeClass('br-current');
                                $a.addClass('br-current')
                            }

                            // remember selected rating
                            $elem.data('barrating').currentRatingValue = value;
                            $elem.data('barrating').currentRatingText = text;

                            $widget.trigger('ratingchange');

                            // onSelect callback
                            userOptions.onSelect.call(
                                this,
                                $elem.data('barrating').currentRatingValue,
                                $elem.data('barrating').currentRatingText
                            );

                            return false;

                        });

                        // attach mouseenter/mouseleave event handlers
                        $all.on({
                            mouseenter:function () {
                                var $a = $(this);

                                $all.removeClass('br-active').removeClass('br-selected');
                                $a.addClass('br-active')[nextAllorPreviousAll]()
                                    .addClass('br-active');

                                $widget.trigger('ratingchange',
                                    [$a.attr('data-rating-value'), $a.attr('data-rating-text')]
                                );
                            }
                        });

                        $widget.on({
                            mouseleave:function () {
                                $all.removeClass('br-active');
                                $widget
                                    .trigger('ratingchange')
                                    .trigger('ratingstyle');
                            }
                        });

                    }

                    // hide the select box
                    $elem.hide();
                }
            }
            this.clear = function () {

                // restore original data
                this.$elem.data('barrating').currentRatingValue = this.$elem.data('barrating').originalRatingValue;
                this.$elem.data('barrating').currentRatingText = this.$elem.data('barrating').originalRatingText;

                this.$widget
                    .trigger('ratingchange')
                    .trigger('ratingstyle');

                // onClear callback
                this.options.onClear.call(
                    this,
                    this.$elem.data('barrating').currentRatingValue,
                    this.$elem.data('barrating').currentRatingText
                );

            }
            this.destroy = function () {

                var value = this.$elem.data('barrating').currentRatingValue;
                var text = this.$elem.data('barrating').currentRatingText;

                this.$elem.removeData('barrating');

                this.$widget.off().remove();

                // show the select box
                this.$elem.show();

                // onDestroy callback
                this.options.onDestroy.call(
                    this,
                    value,
                    text
                );

            }
            this.set = function (value) {

                // set data
                this.$elem.data('barrating').currentRatingValue = value;
                this.$elem.data('barrating').currentRatingText = this.$elem.find('option[value="' + value + '"]').text();

                this.$widget
                    .trigger('ratingchange')
                    .trigger('ratingstyle');

            }
        }

        BarRating.prototype.init = function (options, elem) {
            var self;
            self = this;
            self.elem = elem;
            self.$elem = $(this.elem);

            return self.options = $.extend({}, $.fn.barrating.defaults, options);
        };

        return BarRating;

    })();

    $.fn.barrating = function (method, options) {
        return this.each(function () {
            var plugin = new BarRating();

            // plugin works with select fields
            if (!$(this).is('select')) {
                $.error('Sorry, this plugin only works with select fields.');
            }

            // method supplied
            if (plugin.hasOwnProperty(method)) {
                plugin.init(options, this);
                if (method == 'show') {
                    return plugin.show(options);
                } else {
                    plugin.$widget = $(this).next('.br-widget');

                    // widget exists?
                    if (plugin.$widget && plugin.$elem.data('barrating')) {
                        return plugin[method](options);
                    }
                }

            // no method supplied or only options supplied
            } else if (typeof method === 'object' || !method) {
                options = method;
                plugin.init(options, this);
                return plugin.show();

            } else {
                $.error('Method ' + method + ' does not exist on jQuery.barrating');
            }

        });
    };
    return $.fn.barrating.defaults = {
        initialRating:null, // initial rating
        showValues:false, // display rating values on the bars?
        showSelectedRating:true, // append a div with a rating to the widget?
        reverse:false, // reverse the rating?
        readonly:false, // make the rating ready-only?
        onSelect:function (value, text) {
        }, // callback fired when a rating is selected
        onClear:function (value, text) {
        }, // callback fired when a rating is cleared
        onDestroy:function (value, text) {
        } // callback fired when a widget is destroyed
    };
})(jQuery);
<commit_msg>comment updated<commit_after>/**
 * jQuery Bar Rating Plugin v1.0.5
 *
 * http://github.com/antennaio/jquery-bar-rating
 *
 * Copyright (c) 2012-2014 Kazik Pietruszewski
 *
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
(function ($) {
    var BarRating, root;

    root = typeof window !== "undefined" && window !== null ? window : global;

    root.BarRating = BarRating = (function () {

        function BarRating() {
            this.show = function () {
                var $elem = this.$elem,
                    $widget,
                    $all,
                    userOptions = this.options,
                    nextAllorPreviousAll,
                    initialOption;

                // run only once
                if (!$elem.data('barrating')) {

                    if (userOptions.initialRating) {
                        initialOption = $('option[value="' + userOptions.initialRating  + '"]', $elem);
                    } else {
                        initialOption = $('option:selected', $elem);
                    }

                    $elem.data('barrating', {

                        // initial rating based on the OPTION value
                        currentRatingValue:initialOption.val(),
                        currentRatingText:initialOption.text(),

                        // rating will be restored by calling destroy method
                        originalRatingValue:initialOption.val(),
                        originalRatingText:initialOption.text()

                    });

                    $widget = $('<div />', { 'class':'br-widget' }).insertAfter($elem);

                    // create A elements that will replace OPTIONs
                    $elem.find('option').each(function () {
                        var val, text, $a, $span;

                        val = $(this).val();

                        // create ratings - but only if val is defined
                        if (val) {
                            text = $(this).text();
                            $a = $('<a />', { href:'#', 'data-rating-value':val, 'data-rating-text':text });
                            $span = $('<span />', { text:(userOptions.showValues) ? text : '' });

                            $widget.append($a.append($span));
                        }

                    });

                    // append .br-current-rating div to the widget
                    if (userOptions.showSelectedRating) {
                        $widget.append($('<div />', { text:'', 'class':'br-current-rating' }));
                    }

                    // first OPTION empty - allow deselecting of ratings
                    $elem.data('barrating').deselectable = (!$elem.find('option:first').val()) ? true : false;

                    // use different jQuery function depending on the 'reverse' setting
                    if (userOptions.reverse) {
                        nextAllorPreviousAll = 'nextAll';
                    } else {
                        nextAllorPreviousAll = 'prevAll';
                    }

                    // additional classes for the widget
                    if (userOptions.reverse) {
                        $widget.addClass('br-reverse');
                    }

                    if (userOptions.readonly) {
                        $widget.addClass('br-readonly');
                    }

                    // rating change event
                    $widget.on('ratingchange',
                        function (event, value, text) {

                            // value or text undefined?
                            value = value ? value : $elem.data('barrating').currentRatingValue;
                            text = text ? text : $elem.data('barrating').currentRatingText;

                            // change selected OPTION in the select box (now hidden)
                            $elem.find('option[value="' + value + '"]').prop('selected', true);

                            $elem.change();

                            // update .br-current-rating div
                            if (userOptions.showSelectedRating) {
                                $(this).find('.br-current-rating').text(text);
                            }

                        }).trigger('ratingchange');

                    // rating style event
                    $widget.on('ratingstyle',
                        function (event) {
                            $widget.find('a').removeClass('br-selected br-current');

                            // add classes
                            $(this).find('a[data-rating-value="' + $elem.data('barrating').currentRatingValue + '"]')
                                .addClass('br-selected br-current')[nextAllorPreviousAll]()
                                .addClass('br-selected');

                        }).trigger('ratingstyle');

                    $all = $widget.find('a');

                    // fast clicks
                    $all.on('touchstart', function (event) {
                        event.preventDefault();
                        event.stopPropagation();

                        $(this).click();
                    });

                    // do not react to click events if rating is read-only
                    if (userOptions.readonly) {
                        $all.on('click', function (event) {
                            event.preventDefault();
                        });
                    }

                    // add interactions
                    if (!userOptions.readonly) {

                        $all.on('click', function (event) {
                            var $a = $(this),
                                value,
                                text;

                            event.preventDefault();

                            $all.removeClass('br-active br-selected');
                            $a.addClass('br-selected')[nextAllorPreviousAll]()
                                .addClass('br-selected');

                            value = $a.attr('data-rating-value');
                            text = $a.attr('data-rating-text');

                            // is current and deselectable?
                            if ($a.hasClass('br-current') && $elem.data('barrating').deselectable) {
                                $a.removeClass('br-selected br-current')[nextAllorPreviousAll]()
                                    .removeClass('br-selected br-current');
                                value = '', text = '';
                            } else {
                                $all.removeClass('br-current');
                                $a.addClass('br-current')
                            }

                            // remember selected rating
                            $elem.data('barrating').currentRatingValue = value;
                            $elem.data('barrating').currentRatingText = text;

                            $widget.trigger('ratingchange');

                            // onSelect callback
                            userOptions.onSelect.call(
                                this,
                                $elem.data('barrating').currentRatingValue,
                                $elem.data('barrating').currentRatingText
                            );

                            return false;

                        });

                        // attach mouseenter/mouseleave event handlers
                        $all.on({
                            mouseenter:function () {
                                var $a = $(this);

                                $all.removeClass('br-active').removeClass('br-selected');
                                $a.addClass('br-active')[nextAllorPreviousAll]()
                                    .addClass('br-active');

                                $widget.trigger('ratingchange',
                                    [$a.attr('data-rating-value'), $a.attr('data-rating-text')]
                                );
                            }
                        });

                        $widget.on({
                            mouseleave:function () {
                                $all.removeClass('br-active');
                                $widget
                                    .trigger('ratingchange')
                                    .trigger('ratingstyle');
                            }
                        });

                    }

                    // hide the select box
                    $elem.hide();
                }
            }
            this.clear = function () {

                // restore original data
                this.$elem.data('barrating').currentRatingValue = this.$elem.data('barrating').originalRatingValue;
                this.$elem.data('barrating').currentRatingText = this.$elem.data('barrating').originalRatingText;

                this.$widget
                    .trigger('ratingchange')
                    .trigger('ratingstyle');

                // onClear callback
                this.options.onClear.call(
                    this,
                    this.$elem.data('barrating').currentRatingValue,
                    this.$elem.data('barrating').currentRatingText
                );

            }
            this.destroy = function () {

                var value = this.$elem.data('barrating').currentRatingValue;
                var text = this.$elem.data('barrating').currentRatingText;

                this.$elem.removeData('barrating');

                this.$widget.off().remove();

                // show the select box
                this.$elem.show();

                // onDestroy callback
                this.options.onDestroy.call(
                    this,
                    value,
                    text
                );

            }
            this.set = function (value) {

                // set data
                this.$elem.data('barrating').currentRatingValue = value;
                this.$elem.data('barrating').currentRatingText = this.$elem.find('option[value="' + value + '"]').text();

                this.$widget
                    .trigger('ratingchange')
                    .trigger('ratingstyle');

            }
        }

        BarRating.prototype.init = function (options, elem) {
            var self;
            self = this;
            self.elem = elem;
            self.$elem = $(this.elem);

            return self.options = $.extend({}, $.fn.barrating.defaults, options);
        };

        return BarRating;

    })();

    $.fn.barrating = function (method, options) {
        return this.each(function () {
            var plugin = new BarRating();

            // plugin works with select fields
            if (!$(this).is('select')) {
                $.error('Sorry, this plugin only works with select fields.');
            }

            // method supplied
            if (plugin.hasOwnProperty(method)) {
                plugin.init(options, this);
                if (method == 'show') {
                    return plugin.show(options);
                } else {
                    plugin.$widget = $(this).next('.br-widget');

                    // widget exists?
                    if (plugin.$widget && plugin.$elem.data('barrating')) {
                        return plugin[method](options);
                    }
                }

            // no method supplied or only options supplied
            } else if (typeof method === 'object' || !method) {
                options = method;
                plugin.init(options, this);
                return plugin.show();

            } else {
                $.error('Method ' + method + ' does not exist on jQuery.barrating');
            }

        });
    };
    return $.fn.barrating.defaults = {
        initialRating:null, // initial rating
        showValues:false, // display rating values on the bars?
        showSelectedRating:true, // append a div with a rating to the widget?
        reverse:false, // reverse the rating?
        readonly:false, // make the rating ready-only?
        onSelect:function (value, text) {
        }, // callback fired when a rating is selected
        onClear:function (value, text) {
        }, // callback fired when a rating is cleared
        onDestroy:function (value, text) {
        } // callback fired when a widget is destroyed
    };
})(jQuery);
<|endoftext|>


<commit_before>$(function() {
	/*
	 * Initialisation de la Map
	 */

	$.fn.googleMap = function(params) {
		params = $.extend( {
			zoom: 10,
			coords: [48.895651, 2.290569],
			type: "ROADMAP",
			debug: false
		}, params);

		// Vérification du type de la carte
		switch(params.type) {
			case 'ROADMAP':
			case 'SATELLITE':
			case 'HYBRID':
			case 'TERRAIN':
				params.type = google.maps.MapTypeId[params.type];
				break;
			default:
				params.type = google.maps.MapTypeId.ROADMAP;
				break;
		}

		// VÃ©rification des coordonnÃ©es du centre de la carte

		this.each(function() {

			var map = new google.maps.Map(this, {
				zoom: params.zoom,
		        center: new google.maps.LatLng(params.coords[0], params.coords[1]),
		        mapTypeId: params.type
			});

			$(this).data('googleMap',    map);
			$(this).data('googleDebug',  params.debug);
			$(this).data('googleMarker', new Array());
			$(this).data('googleBound',  new google.maps.LatLngBounds());
		});

        return this;
    }

    /*
     * Ajouter un point
     */
    $.fn.addMarker = function(params) {
		params = $.extend( {
			coords  : false,
			address : false,
			url     : false,
			id      : false,
			icon    : false,
			title   : "",
			text    : "",
			success : function() {}
		}, params);

		this.each(function() {
			$this = $(this);

        	if(!$(this).data('googleMap')) {
	        	console.error("jQuery googleMap : Unable to add a marker where there is no map !");
	        	return false;
        	}

        	if(!params.coords && !params.address) {
        		if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to add a marker if you don't tell us where !");
	        	return false;
        	}

        	if(params.address && typeof params.address == "string") {
	        	geocoder = new google.maps.Geocoder();

			    geocoder.geocode({
			    	address  : params.address,
			    	bounds   : $this.data('googleBound'),
			    	language : 'french'
			    }, function(results, status) {
			        if (status == google.maps.GeocoderStatus.OK) {

			        	$this.data('googleBound').extend(results[0].geometry.location);

			            if(params.icon) {
			        		var marker = new google.maps.Marker({
				                map: $this.data('googleMap'),
				                position: results[0].geometry.location,
				                title: params.title,
				                icon: params.icon
				            });
		        		} else {

			        		var marker = new google.maps.Marker({
				                map: $this.data('googleMap'),
				                position: results[0].geometry.location,
				                title: params.title
				            });
		        		}

			            if(params.title != "" && params.text != "" && !params.url) {
				            var infowindow = new google.maps.InfoWindow({
					            content: "
"+params.title+"
"+params.text
					        });

					        var map = $this.data('googleMap');
					        google.maps.event.addListener(marker, 'click', function() {
						        infowindow.open(map, marker);
					        });
			            } else if(params.url) {
				            google.maps.event.addListener(marker, 'click', function() {
				                document.location = params.url;
				            });
			            }

			            if(!params.id) {
			           		$this.data('googleMarker').push(marker);
			            } else {
				            $this.data('googleMarker')[params.id] = marker;
			            }

			            if($this.data('googleMarker').length == 1) {
				            $this.data('googleMap').setCenter(results[0].geometry.location);
				            $this.data('googleMap').setZoom(9);
			            } else {
				        	$this.data('googleMap').fitBounds($this.data('googleBound'));
			            }

			            params.success({
				            lat: results[0].geometry.location.Xa,
				            lon: results[0].geometry.location.Ya
			            });

			        } else {
			            if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to find the place asked for the marker ("+status+")");
			        }
			    });
        	} else {

        		$this.data('googleBound').extend(new google.maps.LatLng(params.coords[0], params.coords[1]));

        		if(params.icon) {
	        		var marker = new google.maps.Marker({
		                map: $this.data('googleMap'),
		                position: new google.maps.LatLng(params.coords[0], params.coords[1]),
		                title: params.title,
		                icon: params.icon
		            });
        		} else {
	        		var marker = new google.maps.Marker({
		                map: $this.data('googleMap'),
		                position: new google.maps.LatLng(params.coords[0], params.coords[1]),
		                title: params.title
		            });
        		}

	            if(params.title != "" && params.text != "" && !params.url) {
		            var infowindow = new google.maps.InfoWindow({
			            content: "
"+params.title+"
"+params.text
			        });

			        var map = $this.data('googleMap');
			        google.maps.event.addListener(marker, 'click', function() {
				        infowindow.open(map, marker);
			        });
	            } else if(params.url) {
		            google.maps.event.addListener(marker, 'click', function() {
		                document.location = params.url;
		            });
	            }

	            if(!params.id) {
	           		$this.data('googleMarker').push(marker);
	            } else {
		            $this.data('googleMarker')[params.id] = marker;
	            }

	            if($this.data('googleMarker').length == 1) {
		            $this.data('googleMap').setCenter(new google.maps.LatLng(params.coords[0], params.coords[1]));
		            $this.data('googleMap').setZoom(9);
	            } else {
		        	$this.data('googleMap').fitBounds($this.data('googleBound'));
	            }

	            params.success({
		            lat: params.coords[0],
		            lon: params.coords[1]
	            });
        	}
        });

        return this;
	}

	$.fn.removeMarker = function(id) {
		this.each(function() {
			$this = $(this);

        	if(!$(this).data('googleMap')) {
	        	console.log("jQuery googleMap : Unable to delete a marker where there is no map !");
	        	return false;
        	}

        	$markers = $(this).data('googleMarker');

        	console.log($markers);

        	if(typeof $markers[id] != 'undefined') {
        		$markers[id].setMap(null);
	        	if($(this).data('googleDebug')) console.log('jQuery googleMap : marker deleted');
        	} else {
	        	if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to delete a marker if it not exists !");
	        	return false;
        	}
		});
	}

	/*
	 * Générer un itinéraire
	 */
	$.fn.addWay = function(params) {
		params = $.extend( {
			start   : false,
			end     : false,
			step    : [],
			route   : false,
			langage : 'french'
		}, params);

		var direction = new google.maps.DirectionsService({
            region: "fr"
        });

        var way       = new google.maps.DirectionsRenderer({
            draggable: true,
            map:       $(this).data('googleMap'),
            panel:     document.getElementById(params.route),
            provideTripAlternatives: true
        });

        // waypoints
        var waypoints = [];

        for(var i in params.step) {
        	var step;
	        if(typeof params.step[i] == "object") {
		        step = new google.maps.LatLng(params.step[i][0], params.step[i][1]);
	        } else {
		        step = params.step[i];
	        }

	        waypoints.push({
	        	location: step,
	        	stopover: true
	        });
        }

		if(typeof params.end != "object") {
			geocoder = new google.maps.Geocoder();
		    geocoder.geocode({
		    	address  : params.end,
		    	bounds   : $(this).data('googleBound'),
		    	language : params.langage
		    }, function(results, status) {
		        if (status == google.maps.GeocoderStatus.OK) {

		        	var request = {
			            origin: params.start,
			            destination: results[0].geometry.location,
			            travelMode: google.maps.DirectionsTravelMode.DRIVING,
			            region: "fr",
			            waypoints: waypoints
			        };

			        direction.route(request, function(response, status) {
			            if (status == google.maps.DirectionsStatus.OK) {
			                way.setDirections(response);
			            } else {
			                alert("Address not found");
			            }
			        });

		        } else {
		            if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to find the place asked for the route ("+status+")");
		        }
		    });
		} else {
			var request = {
	            origin: params.start,
	            destination: new google.maps.LatLng(params.end[0], params.end[1]),
	            travelMode: google.maps.DirectionsTravelMode.DRIVING,
	            region: "fr",
			    waypoints: waypoints
	        };

	        direction.route(request, function(response, status) {
	            if (status == google.maps.DirectionsStatus.OK) {
	                way.setDirections(response);
	            } else {
	                alert("Address not found");
	            }
	        });
		}

		return this;
	}
});<commit_msg>Bugfix #3<commit_after>$(function() {
	/*
	 * Initialisation de la Map
	 */

	$.fn.googleMap = function(params) {
		params = $.extend( {
			zoom: 10,
			coords: [48.895651, 2.290569],
			type: "ROADMAP",
			debug: false
		}, params);

		// Vérification du type de la carte
		switch(params.type) {
			case 'ROADMAP':
			case 'SATELLITE':
			case 'HYBRID':
			case 'TERRAIN':
				params.type = google.maps.MapTypeId[params.type];
				break;
			default:
				params.type = google.maps.MapTypeId.ROADMAP;
				break;
		}

		// VÃ©rification des coordonnÃ©es du centre de la carte

		this.each(function() {

			var map = new google.maps.Map(this, {
				zoom: params.zoom,
		        center: new google.maps.LatLng(params.coords[0], params.coords[1]),
		        mapTypeId: params.type
			});

			$(this).data('googleMap',    map);
			$(this).data('googleDebug',  params.debug);
			$(this).data('googleMarker', new Array());
			$(this).data('googleBound',  new google.maps.LatLngBounds());
		});

        return this;
    }

    /*
     * Ajouter un point
     */
    $.fn.addMarker = function(params) {
		params = $.extend( {
			coords  : false,
			address : false,
			url     : false,
			id      : false,
			icon    : false,
			title   : "",
			text    : "",
			success : function() {}
		}, params);

		this.each(function() {
			$this = $(this);

        	if(!$(this).data('googleMap')) {
	        	console.error("jQuery googleMap : Unable to add a marker where there is no map !");
	        	return false;
        	}

        	if(!params.coords && !params.address) {
        		if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to add a marker if you don't tell us where !");
	        	return false;
        	}

        	if(params.address && typeof params.address == "string") {
	        	geocoder = new google.maps.Geocoder();

			    geocoder.geocode({
			    	address  : params.address,
			    	bounds   : $this.data('googleBound'),
			    	language : 'french'
			    }, function(results, status) {
			        if (status == google.maps.GeocoderStatus.OK) {

			        	$this.data('googleBound').extend(results[0].geometry.location);

			            if(params.icon) {
			        		var marker = new google.maps.Marker({
				                map: $this.data('googleMap'),
				                position: results[0].geometry.location,
				                title: params.title,
				                icon: params.icon
				            });
		        		} else {

			        		var marker = new google.maps.Marker({
				                map: $this.data('googleMap'),
				                position: results[0].geometry.location,
				                title: params.title
				            });
		        		}

			            if(params.title != "" && params.text != "" && !params.url) {
				            var infowindow = new google.maps.InfoWindow({
					            content: "
"+params.title+"
"+params.text
					        });

					        var map = $this.data('googleMap');
					        google.maps.event.addListener(marker, 'click', function() {
						        infowindow.open(map, marker);
					        });
			            } else if(params.url) {
				            google.maps.event.addListener(marker, 'click', function() {
				                document.location = params.url;
				            });
			            }

			            if(!params.id) {
			           		$this.data('googleMarker').push(marker);
			            } else {
				            $this.data('googleMarker')[params.id] = marker;
			            }

			            if($this.data('googleMarker').length == 1) {
				            $this.data('googleMap').setCenter(results[0].geometry.location);
				            $this.data('googleMap').setZoom($this.data('googleMap').getZoom());
			            } else {
				        	$this.data('googleMap').fitBounds($this.data('googleBound'));
			            }

			            params.success({
				            lat: results[0].geometry.location.Xa,
				            lon: results[0].geometry.location.Ya
			            });

			        } else {
			            if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to find the place asked for the marker ("+status+")");
			        }
			    });
        	} else {

        		$this.data('googleBound').extend(new google.maps.LatLng(params.coords[0], params.coords[1]));

        		if(params.icon) {
	        		var marker = new google.maps.Marker({
		                map: $this.data('googleMap'),
		                position: new google.maps.LatLng(params.coords[0], params.coords[1]),
		                title: params.title,
		                icon: params.icon
		            });
        		} else {
	        		var marker = new google.maps.Marker({
		                map: $this.data('googleMap'),
		                position: new google.maps.LatLng(params.coords[0], params.coords[1]),
		                title: params.title
		            });
        		}

	            if(params.title != "" && params.text != "" && !params.url) {
		            var infowindow = new google.maps.InfoWindow({
			            content: "
"+params.title+"
"+params.text
			        });

			        var map = $this.data('googleMap');
			        google.maps.event.addListener(marker, 'click', function() {
				        infowindow.open(map, marker);
			        });
	            } else if(params.url) {
		            google.maps.event.addListener(marker, 'click', function() {
		                document.location = params.url;
		            });
	            }

	            if(!params.id) {
	           		$this.data('googleMarker').push(marker);
	            } else {
		            $this.data('googleMarker')[params.id] = marker;
	            }

	            if($this.data('googleMarker').length == 1) {
		            $this.data('googleMap').setCenter(new google.maps.LatLng(params.coords[0], params.coords[1]));
		            $this.data('googleMap').setZoom($this.data('googleMap').getZoom());
	            } else {
		        	$this.data('googleMap').fitBounds($this.data('googleBound'));
	            }

	            params.success({
		            lat: params.coords[0],
		            lon: params.coords[1]
	            });
        	}
        });

        return this;
	}

	$.fn.removeMarker = function(id) {
		this.each(function() {
			$this = $(this);

        	if(!$(this).data('googleMap')) {
	        	console.log("jQuery googleMap : Unable to delete a marker where there is no map !");
	        	return false;
        	}

        	$markers = $(this).data('googleMarker');

        	console.log($markers);

        	if(typeof $markers[id] != 'undefined') {
        		$markers[id].setMap(null);
	        	if($(this).data('googleDebug')) console.log('jQuery googleMap : marker deleted');
        	} else {
	        	if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to delete a marker if it not exists !");
	        	return false;
        	}
		});
	}

	/*
	 * Générer un itinéraire
	 */
	$.fn.addWay = function(params) {
		params = $.extend( {
			start   : false,
			end     : false,
			step    : [],
			route   : false,
			langage : 'french'
		}, params);

		var direction = new google.maps.DirectionsService({
            region: "fr"
        });

        var way       = new google.maps.DirectionsRenderer({
            draggable: true,
            map:       $(this).data('googleMap'),
            panel:     document.getElementById(params.route),
            provideTripAlternatives: true
        });

        // waypoints
        var waypoints = [];

        for(var i in params.step) {
        	var step;
	        if(typeof params.step[i] == "object") {
		        step = new google.maps.LatLng(params.step[i][0], params.step[i][1]);
	        } else {
		        step = params.step[i];
	        }

	        waypoints.push({
	        	location: step,
	        	stopover: true
	        });
        }

		if(typeof params.end != "object") {
			geocoder = new google.maps.Geocoder();
		    geocoder.geocode({
		    	address  : params.end,
		    	bounds   : $(this).data('googleBound'),
		    	language : params.langage
		    }, function(results, status) {
		        if (status == google.maps.GeocoderStatus.OK) {

		        	var request = {
			            origin: params.start,
			            destination: results[0].geometry.location,
			            travelMode: google.maps.DirectionsTravelMode.DRIVING,
			            region: "fr",
			            waypoints: waypoints
			        };

			        direction.route(request, function(response, status) {
			            if (status == google.maps.DirectionsStatus.OK) {
			                way.setDirections(response);
			            } else {
			                alert("Address not found");
			            }
			        });

		        } else {
		            if($(this).data('googleDebug')) console.error("jQuery googleMap : Unable to find the place asked for the route ("+status+")");
		        }
		    });
		} else {
			var request = {
	            origin: params.start,
	            destination: new google.maps.LatLng(params.end[0], params.end[1]),
	            travelMode: google.maps.DirectionsTravelMode.DRIVING,
	            region: "fr",
			    waypoints: waypoints
	        };

	        direction.route(request, function(response, status) {
	            if (status == google.maps.DirectionsStatus.OK) {
	                way.setDirections(response);
	            } else {
	                alert("Address not found");
	            }
	        });
		}

		return this;
	}
});
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();

var piensos = [
    {
      id: 1,
      marca: "Purina",
      modelo: "Junior Pro",
      peso: 2.5,
      precio: 5.99,
      descripcion: "Indicado para perros jovenes",
      fCaducidad: "1453912360",
      logo: "sdfasdfasf"
    },
    {
      id: 2,
      marca: "acANA",
      modelo: "Junior Pro",
      peso: 2.5,
      precio: 5.99,
      descripcion: "Indicado para perros jovenes",
      fCaducidad: "1453912360",
      logo: "sdfasdfasf"
    },
    {
	  id:3,
	  marca: "Friskies",
	  modelo: "Perros enanos",
	  peso: 300,
	  precio: 60,
	  descripcion: "Friskies, para perros canijos",
	  fCaducidad: 1453999136
	 },
	 {
	  id:4,
	  marca: "Firskies",
	  modelo: "Perros grandes",
	  peso: 600,
	  precio: 49.99,
	  descripcion: "Friskies, para perros de verdad",
	  fCaducidad: 1485535136
	 },
	 {
	  id:5,
	  marca: "McPerris",
	  modelo: "Plus",
	  peso: 1000,
	  precio: 35.99,
	  descripcion: "Para los más perros",
	  fCaducidad: 1456591136
	 },
	 {
	  id:6,
	  marca: "Doggie",
	  modelo: "Adulto",
	  peso: 100,
	  precio: 43.80,
	  descripcion: "Para perrear",
	  fCaducidad: 1454517536
	}
  ]

/* GET piensos listing. */
router.get('/', function(req, res, next) {

  res.status(200).send(piensos);

});

router.get('/:id', function(req, res, next) {

    var len = piensos.length;
	var resul = "Elemento no encontrado";
    for(var i = 0; i<len; i++){
        var item = piensos[i];

        if(item.id === parseInt(req.params.id)) {
        	resul = item;
        	break;
        };
    }

    res.status(200).send(resul);

});

module.exports = router;
<commit_msg>Update index.js<commit_after>var express = require('express');
var router = express.Router();

var piensos = [
		{ pienso: { id: 1, marca: "Perrina", modelo: "Junior Pro", peso: 2.5, precio: 5.99, descripcion: "Indicado para perros jovenes", fCaducidad: "1453912360", logo: "sdfasdfasf" } },
		{ pienso: { id: 2, marca: "Akana", modelo: "Junior Pro", peso: 2.5, precio: 5.99, descripcion: "Indicado para perros jovenes", fCaducidad: "1453912360", logo: "sdfasdfasf" } },
		{ pienso: { id: 3, marca: "Firskies", modelo: "Perros Minor", peso: 300, precio: 60, descripcion: "Friskies, para perros canijos", fCaducidad: 1453999136 } },
		{ pienso: { id: 4, marca: "Firskies", modelo: "Perros grandes", peso: 600, precio: 49.99, descripcion: "Friskies, para perros de verdad", fCaducidad: 1485535136 } },
		{ pienso: { id:5, marca: "McPerris", modelo: "Plus", peso: 1000, precio: 35.99, descripcion: "Para los más perros", fCaducidad: 1456591136 } },
		{ pienso: { id: 6, marca: "Doggie", modelo: "Adulto", peso: 100, precio: 43.80, descripcion: "Para perrear", fCaducidad: 1454517536 } }
	];

/* GET piensos listing. */
router.get('/', function(req, res, next) {
  res.status(200).send(piensos);

});

router.get('/:id', function(req, res, next) {

    var len = piensos.length;
	var resul = "Elemento no encontrado";
    for(var i = 0; i<len; i++){
        var item = piensos[i];

        if(item.id === parseInt(req.params.id)) {
        	resul = item;
        	break;
        };
    }

    res.status(200).send(resul);

});

module.exports = router;
<|endoftext|>


<commit_before>// Copyright 2018, University of Colorado Boulder

/**
 * The "kebab" menu icon, 3 dots stacked vertically that look like a shish kebob.
 * See https://github.com/phetsims/joist/issues/544
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( require => {
  'use strict';

  // modules
  const joist = require( 'JOIST/joist' );
  const Path = require( 'SCENERY/nodes/Path' );
  const Shape = require( 'KITE/Shape' );

  // const
  const CIRCLE_RADIUS = 2.5;

  class KebabMenuIcon extends Path {

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

      const shape = new Shape();
      for ( let i = 0; i < 3; i++ ) {
        const circleOffset = i * 3.5 * CIRCLE_RADIUS;
        shape.arc( 0, circleOffset, CIRCLE_RADIUS, 0, 2 * Math.PI, false );
      }

      super( shape, options );
    }
  }

  return joist.register( 'KebabMenuIcon', KebabMenuIcon );
} ); <commit_msg>use Shape.circle instead of Shape.arc, #544<commit_after>// Copyright 2018, University of Colorado Boulder

/**
 * The "kebab" menu icon, 3 dots stacked vertically that look like a shish kebob.
 * See https://github.com/phetsims/joist/issues/544
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( require => {
  'use strict';

  // modules
  const joist = require( 'JOIST/joist' );
  const Path = require( 'SCENERY/nodes/Path' );
  const Shape = require( 'KITE/Shape' );

  // const
  const CIRCLE_RADIUS = 2.5;

  class KebabMenuIcon extends Path {

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

      const shape = new Shape();
      for ( let i = 0; i < 3; i++ ) {
        shape.circle( 0, i * 3.5 * CIRCLE_RADIUS, CIRCLE_RADIUS );
      }

      super( shape, options );
    }
  }

  return joist.register( 'KebabMenuIcon', KebabMenuIcon );
} ); <|endoftext|>


<commit_before>(function(exports) {

var PashTokenizer = function (){
  this.reset();
};

PashTokenizer.prototype = {
  //      1     2     34         5          678                9    10                     11           12                    13
  regex: /(\s+)|(\w+)|(("[^"]*")|('[^']*'))|(((\/\/|--)[^\n]*)|(\/\*([^\*]|\*[^\/])*\*\/))|(\[[^\]]+\])|([\.,\*\-\+\(\):<>=])|(;)/g,
  tokenTypes: {
    1: "whitespace",
    2: "identifier",
    3: "string",
    4: "double quoted string",
    5: "single quoted string",
    6: "comment",
    7: "comment line",
    8: false,
    9: "comment block",
    10: false,
    11: "square braces",
    12: "operator",
    13: "terminator"
  },
  reset: function(){
    if (this.tokens) this.tokens.length = 0;
    this.currentToken = -1;
  },
  getRegex: function(){
    var flags = "";
    if (this.regex.global) flags += "g"
    if (this.regex.ignoreCase) flags += "i"
    return new RegExp(this.regex.source, flags);
  },
  tokenize: function(text){
    var re = this.getRegex();
    var match, token, i, n, num = 0;
    var type, tokens = [];
    while (match = re.exec(text)){
      num++;
      //ignore whitespace and comments
      if (match[0] === ";" && typeof(terminator) === "undefined") {
        terminator = num;
        terminatorColumn = re.lastIndex;
      }
      token = {text: match[0], index: re.lastIndex};
      for (i = match.length - 1; i >= 0; i--){
        if(match[i] && (type = this.tokenTypes[i])) {
          token.type = type;
          break;
        }
      }
      tokens.push(token);
    }
    this.tokens = tokens;
    this.currentToken = 0;
  },
  hasMoreTokens: function(){
    return this.tokens ? this.currentToken < this.tokens.length : false;
  },
  nextToken: function(){
    var token = null;
    var ignoreTokens = {
      whitespace: true,
      "comment line": true,
      "comment block": true,
    };
    while (this.hasMoreTokens()) {
      token = this.tokens[this.currentToken++];
      if (ignoreTokens[token.type]) {
        token = null;
        continue;
      }
      break;
    }
    return token;
  }
};

exports.PashTokenizer = PashTokenizer;
})(typeof(exports) === "object" ? exports : window);
<commit_msg>Fixed a problem in hasMoreTokens() - ignored tokens would not be taken into account.<commit_after>(function(exports) {

var PashTokenizer = function (){
  this.reset();
};

PashTokenizer.prototype = {
  //      1     2     34         5          678                9    10                     11           12                    13
  regex: /(\s+)|(\w+)|(("[^"]*")|('[^']*'))|(((\/\/|--)[^\n]*)|(\/\*([^\*]|\*[^\/])*\*\/))|(\[[^\]]+\])|([\.,\*\-\+\(\):<>=])|(;)/g,
  tokenTypes: {
    1: "whitespace",
    2: "identifier",
    3: "string",
    4: "double quoted string",
    5: "single quoted string",
    6: "comment",
    7: "comment line",
    8: false,
    9: "comment block",
    10: false,
    11: "square braces",
    12: "operator",
    13: "terminator"
  },
  reset: function(){
    if (this.tokens) this.tokens.length = 0;
    this.currentToken = -1;
  },
  getRegex: function(){
    var flags = "";
    if (this.regex.global) flags += "g"
    if (this.regex.ignoreCase) flags += "i"
    return new RegExp(this.regex.source, flags);
  },
  tokenize: function(text){
    var re = this.getRegex();
    var match, token, i, n, num = 0;
    var type, tokens = [];
    while (match = re.exec(text)){
      num++;
      //ignore whitespace and comments
      if (match[0] === ";" && typeof(terminator) === "undefined") {
        terminator = num;
        terminatorColumn = re.lastIndex;
      }
      token = {text: match[0], index: re.lastIndex};
      for (i = match.length - 1; i >= 0; i--){
        if(match[i] && (type = this.tokenTypes[i])) {
          token.type = type;
          break;
        }
      }
      tokens.push(token);
    }
    this.tokens = tokens;
    this.currentToken = 0;
  },
  hasMoreTokens: function(){
    var tokens = this.tokens;
    if (!tokens) {
      return false;
    }
    var n = tokens.length, currentToken = this.currentToken;
    if (currentToken >= n) {
      return false;
    }
    for (i = currentToken; i < n; i++){
      if (this.isIgnoredToken(tokens[i])) {
        continue;
      }
      return true;
    }
    return false;
  },
  ignoredTokens: {
    whitespace: true,
    "comment line": true,
    "comment block": true
  },
  isIgnoredToken: function(type){
    if (type.type) {
      type = type.type;
    }
    return Boolean(this.ignoredTokens[type]);
  },
  nextToken: function(){
    var token = null;
    var ignoredTokens = this.ignoredTokens;
    while (this.hasMoreTokens()) {
      token = this.tokens[this.currentToken++];
      if (this.isIgnoredToken(token)) {
        token = null;
        continue;
      }
      break;
    }
    return token;
  }
};

exports.PashTokenizer = PashTokenizer;
})(typeof(exports) === "object" ? exports : window);
<|endoftext|>


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

/**
 * Together.js provides an API for accessing the simulation for enhanced features.  This file defines common data types
 * that appear in the simulation-specific files.
 *
 * I wasn't sure whether this file belonged in (a) chipper, (b) joist, (c) a new together-api repo, or (d) the together repo.
 * or (e) within the repo where each thing is defined (Color in scenery, Vector2 in dot, etc).  Or (f) one togetherAPI file
 * per repo???  (d) seemed contraindicated since it is under different licensing, but it would be advantageous to develop
 * each sim API with the sim itself, so it needs to have appropriate licensing.
 * Keeping it all consolidated seems like that would make it very easy to identify API changes.
 * Putting it in joist means we don't need to change any sim config files, since everything already conveniently imports Joist.
 * Let's discuss it.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  var Node = {
    name: 'Node',
    visible: {
      type: 'boolean'
    },

    // Just for demonstration purposes, we may not really want these in the public API
    left: {
      type: 'number'
    },
    right: {
      type: 'number'
    },
    top: {
      type: 'number'
    },
    bottom: {
      type: 'number'
    },
    rotation: {
      type: 'number'
    }
  };

  var Button = {
    name: 'Button',
    parent: Node
  };

  var ResetAllButton = {
    name: 'ResetAllButton',
    parent: Button
  };

  var Faucet = {
    name: 'Faucet',
    parent: Node
  };

  var ComboBox = {
    name: 'ComboBox',
    parent: Node // not exactly a button, see implementation
  };

  var ComboBoxListItem = {
    name: 'ComboBoxButton',
    parent: Button // Also a special case
  };

  var RadioButton = {
    name: 'RadioButton',
    parent: Button
  };

  var CheckBox = {
    name: 'CheckBox',
    parent: Node
  };

  var Boolean = {
    name: 'boolean'
  };

  var Number = {
    name: 'number'
  };

  var String = {
    name: 'String'
  };

  var Color = {
    name: 'Color'
  };

  // TODO: I would like this to be capitalized since it is a type, but jshint complains
  // TODO: and I'd prefer not to use new().  Perhaps a JSHint ignore?
  /**
   * Parameterized type for Properties
   * @param type
   * @returns {{name: string, value: {type: *}}}
   * @constructor
   */
  var property = function( type ) {
    return {
      name: 'Property',
      value: {
        type: type
      }
    };
  };

  var Sim = {
    name: 'Sim'
  };

  var Vector2 = {
    name: 'Vector2'
  };

  var Slider = {
    name: 'Slider',
    parent: Node
  };

  var PhetButton = {
    name: 'PhetButton',
    parent: Button
  };

  var MenuItem = {
    name: 'MenuItem',
    parent: Button
  };

  var OnOffSwitch = {
    name: 'OnOffSwitch',
    parent: Node
  };

  var PlayPauseButton = {
    name: 'PlayPauseButton',
    parent: Node
  };

  return {
    Node: Node,
    ResetAllButton: ResetAllButton,
    Button: Button,
    Faucet: Faucet,
    property: property,
    ComboBox: ComboBox,
    ComboBoxListItem: ComboBoxListItem,
    RadioButton: RadioButton,
    Boolean: Boolean,
    Color: Color,
    Sim: Sim,
    Vector2: Vector2,
    Slider: Slider,
    PhetButton: PhetButton,
    MenuItem: MenuItem,
    CheckBox: CheckBox,
    Number: Number,
    String: String,
    OnOffSwitch: OnOffSwitch,
    PlayPauseButton: PlayPauseButton,
    createSingleScreen: function( screenAPI ) {
      var singleScreenJoistAPI = {
        // TODO: Mix in joist components from another source, so they can be easily shared.
        'sim': { type: Sim },
        'navigationBar.phetButton': { type: PhetButton },
        'navigationBar.phetMenu.phetWebsiteButton': { type: MenuItem },
        'navigationBar.phetMenu.aboutButton': { type: MenuItem },
        'navigationBar.phetMenu.reportAProblemButton': { type: MenuItem },
      };
      for ( var element in screenAPI ) {
        if ( screenAPI.hasOwnProperty( element ) ) {
          assert && assert( !singleScreenJoistAPI.hasOwnProperty( element ), 'key collision' );
          singleScreenJoistAPI[ element ] = screenAPI[ element ];
        }
      }
      return singleScreenJoistAPI;
    },
    createMultipleScreen: function( screenAPIs ) {
      var singleScreenJoistAPI = {

        // TODO: Factor out shared items from above
        'sim': { type: Sim },
        'navigationBar.phetButton': { type: PhetButton },
        'navigationBar.phetMenu.phetWebsiteButton': { type: MenuItem },
        'navigationBar.phetMenu.aboutButton': { type: MenuItem },
        'navigationBar.phetMenu.reportAProblemButton': { type: MenuItem },
        'sim.screenIndex': { type: property( Number ) },
        'sim.showHomeScreen': { type: property( Boolean ) },
        'navigationBar.homeButton': { type: Button }
      };
      for ( var i = 0; i < screenAPIs.length; i++ ) {
        var screenAPI = screenAPIs[ i ];
        for ( var element in screenAPI ) {
          if ( screenAPI.hasOwnProperty( element ) ) {
            assert && assert( !singleScreenJoistAPI.hasOwnProperty( element ), 'key collision' );
            singleScreenJoistAPI[ element ] = screenAPI[ element ];
          }
        }
      }

      return singleScreenJoistAPI;
    }
  };
} );<commit_msg>Properties with IDs must appear in the public API<commit_after>//  Copyright 2002-2014, University of Colorado Boulder

/**
 * Together.js provides an API for accessing the simulation for enhanced features.  This file defines common data types
 * that appear in the simulation-specific files.
 *
 * I wasn't sure whether this file belonged in (a) chipper, (b) joist, (c) a new together-api repo, or (d) the together repo.
 * or (e) within the repo where each thing is defined (Color in scenery, Vector2 in dot, etc).  Or (f) one togetherAPI file
 * per repo???  (d) seemed contraindicated since it is under different licensing, but it would be advantageous to develop
 * each sim API with the sim itself, so it needs to have appropriate licensing.
 * Keeping it all consolidated seems like that would make it very easy to identify API changes.
 * Putting it in joist means we don't need to change any sim config files, since everything already conveniently imports Joist.
 * Let's discuss it.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  var Node = {
    name: 'Node',
    visible: {
      type: 'boolean'
    },

    // Just for demonstration purposes, we may not really want these in the public API
    left: {
      type: 'number'
    },
    right: {
      type: 'number'
    },
    top: {
      type: 'number'
    },
    bottom: {
      type: 'number'
    },
    rotation: {
      type: 'number'
    }
  };

  var Button = {
    name: 'Button',
    parent: Node
  };

  var ResetAllButton = {
    name: 'ResetAllButton',
    parent: Button
  };

  var Faucet = {
    name: 'Faucet',
    parent: Node
  };

  var ComboBox = {
    name: 'ComboBox',
    parent: Node // not exactly a button, see implementation
  };

  var ComboBoxListItem = {
    name: 'ComboBoxButton',
    parent: Button // Also a special case
  };

  var RadioButton = {
    name: 'RadioButton',
    parent: Button
  };

  var CheckBox = {
    name: 'CheckBox',
    parent: Node
  };

  var Boolean = {
    name: 'boolean'
  };

  var Number = {
    name: 'number'
  };

  var String = {
    name: 'String'
  };

  var Color = {
    name: 'Color'
  };

  // TODO: I would like this to be capitalized since it is a type, but jshint complains
  // TODO: and I'd prefer not to use new().  Perhaps a JSHint ignore?
  /**
   * Parameterized type for Properties
   * @param type
   * @returns {{name: string, value: {type: *}}}
   * @constructor
   */
  var property = function( type ) {
    return {
      name: 'Property',
      value: {
        type: type
      }
    };
  };

  var Sim = {
    name: 'Sim'
  };

  var Vector2 = {
    name: 'Vector2'
  };

  var Slider = {
    name: 'Slider',
    parent: Node
  };

  var PhetButton = {
    name: 'PhetButton',
    parent: Button
  };

  var MenuItem = {
    name: 'MenuItem',
    parent: Button
  };

  var OnOffSwitch = {
    name: 'OnOffSwitch',
    parent: Node
  };

  var PlayPauseButton = {
    name: 'PlayPauseButton',
    parent: Node
  };

  return {
    Node: Node,
    ResetAllButton: ResetAllButton,
    Button: Button,
    Faucet: Faucet,
    property: property,
    ComboBox: ComboBox,
    ComboBoxListItem: ComboBoxListItem,
    RadioButton: RadioButton,
    Boolean: Boolean,
    Color: Color,
    Sim: Sim,
    Vector2: Vector2,
    Slider: Slider,
    PhetButton: PhetButton,
    MenuItem: MenuItem,
    CheckBox: CheckBox,
    Number: Number,
    String: String,
    OnOffSwitch: OnOffSwitch,
    PlayPauseButton: PlayPauseButton,
    createSingleScreen: function( screenAPI ) {
      var singleScreenJoistAPI = {
        // TODO: Mix in joist components from another source, so they can be easily shared.
        'sim': { type: Sim },
        'navigationBar.phetButton': { type: PhetButton },
        'navigationBar.phetMenu.phetWebsiteButton': { type: MenuItem },
        'navigationBar.phetMenu.aboutButton': { type: MenuItem },
        'navigationBar.phetMenu.reportAProblemButton': { type: MenuItem },
        'sim.screenIndex': { type: property( Number ) },
        'sim.showHomeScreen': { type: property( Boolean ) }
      };
      for ( var element in screenAPI ) {
        if ( screenAPI.hasOwnProperty( element ) ) {
          assert && assert( !singleScreenJoistAPI.hasOwnProperty( element ), 'key collision' );
          singleScreenJoistAPI[ element ] = screenAPI[ element ];
        }
      }
      return singleScreenJoistAPI;
    },
    createMultipleScreen: function( screenAPIs ) {
      var singleScreenJoistAPI = {

        // TODO: Factor out shared items from above
        'sim': { type: Sim },
        'navigationBar.phetButton': { type: PhetButton },
        'navigationBar.phetMenu.phetWebsiteButton': { type: MenuItem },
        'navigationBar.phetMenu.aboutButton': { type: MenuItem },
        'navigationBar.phetMenu.reportAProblemButton': { type: MenuItem },
        'sim.screenIndex': { type: property( Number ) },
        'sim.showHomeScreen': { type: property( Boolean ) },
        'navigationBar.homeButton': { type: Button }
      };
      for ( var i = 0; i < screenAPIs.length; i++ ) {
        var screenAPI = screenAPIs[ i ];
        for ( var element in screenAPI ) {
          if ( screenAPI.hasOwnProperty( element ) ) {
            assert && assert( !singleScreenJoistAPI.hasOwnProperty( element ), 'key collision' );
            singleScreenJoistAPI[ element ] = screenAPI[ element ];
          }
        }
      }

      return singleScreenJoistAPI;
    }
  };
} );<|endoftext|>


<commit_before>/*global require: false, module: false */
/*eslint-env browser */
'use strict';

var React = require('react');
var slugify = require('./slugify');
var {Navigation} = require('react-router');
var AutoSuggest = require('react-autosuggest');
var _ = require('underscore');
require('./css/Autosuggest.css');

var maxSuggestions = 10;
function getSuggestions(data, input) {
	var matchStr = input.toLowerCase();
	return _.first(_.filter(data, s => s.toLowerCase().indexOf(matchStr) === 0),
			maxSuggestions);
}

function renderSuggestion(suggestion, input) {
	return (

			{suggestion.slice(0, input.length)}
			{suggestion.slice(input.length)}

   );
}

var VariantSearch = React.createClass({
	mixins: [Navigation],
	onClick: function (ev) {
		ev.stopPropagation();
		var value = React.findDOMNode(this.refs.input).value;
		this.props.onSearch(value);
	},
	showHelp: function (title) {
		this.transitionTo(`/help#${slugify(title)}`);
	},
	onChange: function (value) {
		var {onChange} = this.props;
		if (onChange) {
			onChange(value);
		}
		this.setState({value: value});
	},
	suggest: function (input, callback) {
		var {suggestions} = this.props;
		// Invoke asynchronously. This makes more sense if doing an ajax call.
		this.cb = setTimeout(() =>
				callback(null, getSuggestions(suggestions, input, callback), 0));
	},
	componentWillUnmount: function () {
		clearTimeout(this.cb);
	},
	onSubmit: function (ev) {
		ev.preventDefault();
		this.props.onSearch(this.state.value);
	},
	getDefaultProps: function () {
		return {
			onSearch: () => {}
		};
	},
	getInitialState: function () {
		return {
			value: this.props.value
		};
	},
	componentWillReceiveProps: function (newProps) {
		this.setState({value: newProps.value});
	},
	render: function () {
		var {id, onSearch} = this.props,
			{value} = this.state;

		return (

				<form onSubmit={this.onSubmit} style={{display: 'inline'}}>
					<input type='submit' style={{display: 'none'}} />

						<AutoSuggest
							id={id}
							className='dropdown open'
							cache={false}
							value={value}
							inputAttributes={{
								className: 'variant-search-input',
								placeholder: "Search Variant such as c.1105G>A",
								onChange: this.onChange
							}}
							showWhen={input => input.trim().length > 1}
							suggestions={this.suggest}
							onSuggestionSelected={v => onSearch(v)}
							suggestionRenderer={renderSuggestion}
							ref='input' />
						 this.showHelp('Searching')}
							className="glyphicon glyphicon-question-sign superscript help"/>

				</form>

		);
	}
});

module.exports = VariantSearch;
<commit_msg>Autocomplete on string len > 0.<commit_after>/*global require: false, module: false */
/*eslint-env browser */
'use strict';

var React = require('react');
var slugify = require('./slugify');
var {Navigation} = require('react-router');
var AutoSuggest = require('react-autosuggest');
var _ = require('underscore');
require('./css/Autosuggest.css');

var maxSuggestions = 10;
function getSuggestions(data, input) {
	var matchStr = input.toLowerCase();
	return _.first(_.filter(data, s => s.toLowerCase().indexOf(matchStr) === 0),
			maxSuggestions);
}

function renderSuggestion(suggestion, input) {
	return (

			{suggestion.slice(0, input.length)}
			{suggestion.slice(input.length)}

   );
}

var VariantSearch = React.createClass({
	mixins: [Navigation],
	onClick: function (ev) {
		ev.stopPropagation();
		var value = React.findDOMNode(this.refs.input).value;
		this.props.onSearch(value);
	},
	showHelp: function (title) {
		this.transitionTo(`/help#${slugify(title)}`);
	},
	onChange: function (value) {
		var {onChange} = this.props;
		if (onChange) {
			onChange(value);
		}
		this.setState({value: value});
	},
	suggest: function (input, callback) {
		var {suggestions} = this.props;
		// Invoke asynchronously. This makes more sense if doing an ajax call.
		this.cb = setTimeout(() =>
				callback(null, getSuggestions(suggestions, input, callback), 0));
	},
	componentWillUnmount: function () {
		clearTimeout(this.cb);
	},
	onSubmit: function (ev) {
		ev.preventDefault();
		this.props.onSearch(this.state.value);
	},
	getDefaultProps: function () {
		return {
			onSearch: () => {}
		};
	},
	getInitialState: function () {
		return {
			value: this.props.value
		};
	},
	componentWillReceiveProps: function (newProps) {
		this.setState({value: newProps.value});
	},
	render: function () {
		var {id, onSearch} = this.props,
			{value} = this.state;

		return (

				<form onSubmit={this.onSubmit} style={{display: 'inline'}}>
					<input type='submit' style={{display: 'none'}} />

						<AutoSuggest
							id={id}
							className='dropdown open'
							cache={false}
							value={value}
							inputAttributes={{
								className: 'variant-search-input',
								placeholder: "Search Variant such as c.1105G>A",
								onChange: this.onChange
							}}
							showWhen={input => input.trim().length > 0}
							suggestions={this.suggest}
							onSuggestionSelected={v => onSearch(v)}
							suggestionRenderer={renderSuggestion}
							ref='input' />
						 this.showHelp('Searching')}
							className="glyphicon glyphicon-question-sign superscript help"/>

				</form>

		);
	}
});

module.exports = VariantSearch;
<|endoftext|>


<commit_before>function DebtProto(){this.getMinPayment=function(){var a;return a="percent"===this.minpaymenttype?Math.max(Math.round(this.balance*this.minpayment),1):this.minpayment,Math.min(a,this.balance)},this.update=function(){return this.balance=this.balance*(1+this.rate/12),this.balance=Math.round(this.balance),this.pay(this.getMinPayment())},this.pay=function(a){var b=0;return this.balance=this.balance-a,this.balance<=0&&(b=-this.balance,this.balance=0,this.minpayment=0),b}}function Debt(a,b,c,d,e){this.name=a,this.balance=b,this.rate=c,this.minpayment=d,this.minpaymenttype=e,$.extend(this,new DebtProto)}function avalanche(a,b,c){var d=c-sumMinpayments(a);for(d+=payDebts(a);d>0;)if(a=getDebtsWithBalances(a),a.length>0){var e=b(a);d=e.pay(d)}else d=0}function payDebts(a){return a.reduce(function(a,b){return a+b.update()},0)}function getDebtsWithBalances(a){return a.filter(function(a){return a.balance>0})}function sumBalances(a){return a.reduce(function(a,b){return a+b.balance},0)}function sumMinpayments(a){return a.reduce(function(a,b){return a+b.getMinPayment()},0)}function totalAccounts(a){return a.reduce(function(a,b){return a+Math.min(b.balance,1)},0)}function lowestBalance(a){return a.reduce(function(a,b){return null==a?b:a.balance>b.balance?b:a.balance===b.balance&&a.rate<b.rate?b:a})}function highestRate(a){return a.reduce(function(a,b){return null==a?b:a.rateb.balance?b:a})}function usingMethod(a,b){for(var c=totalAccounts(a),d=sumMinpayments(a),e={balances:[["month","balance","minimum payment"],[0,sumBalances(a),sumMinpayments(a)]],accounts:[["month","number of debts"],[0,c]],totalPaid:0,months:0},f=1,g=sumBalances(a);g>0&&f<=500;g=sumBalances(a),f++){"undefined"!=typeof b?avalanche(a,b,d):payDebts(a),f%12===0&&e.balances.push([f,g,sumMinpayments(a)]);var h=totalAccounts(a);h!==c&&(e.accounts.push([f,h]),c=h),"undefined"!=typeof b?d<sumBalances(a)?e.totalPaid=e.totalPaid+d:e.totalPaid=e.totalPaid+sumBalances(a):e.totalPaid=e.totalPaid+sumMinpayments(a)}return e.balances.push([f,sumBalances(a),sumMinpayments(a)]),e.months=f,e}function getResults(a){var b=JSON.parse(JSON.stringify(a));b.forEach(function(a){$.extend(a,new DebtProto)});var c=JSON.parse(JSON.stringify(a));c.forEach(function(a){$.extend(a,new DebtProto)});var d=JSON.parse(JSON.stringify(a));d.forEach(function(a){$.extend(a,new DebtProto)});var e={highestRate:usingMethod(b,highestRate),lowestBalance:usingMethod(c,lowestBalance),justPayments:usingMethod(d)};return e}function getTimeString(a){var b=Math.floor(a/12),c=a-12*b;return b+" years "+c+" months"}function generateRow(a){var b="<input type='text' name='name' value='"+a.name+"' required />",c="$<input type='number' name='balance' class='input-dollar' min='0' value='"+a.balance+"' required />",d="<input type='number' name='rate' class='input-percent' min='0' max='100' step='0.01' value='"+100*a.rate+"' required />%",e="<input type='number' name='minpayment' min='0' value='";e+="percent"===a.minpaymenttype?100*a.minpayment:a.minpayment,e+="' required />";var f="<select name='minpaymenttype'><option value='dollar'"+("dollar"===a.minpaymenttype?" selected":"")+">dollar</option><option value='percent'"+("percent"===a.minpaymenttype?" selected":"")+">percent</option></select>",g="
"+b+"	"+c+"	"+d+"	"+e+"	"+f+"
";return g}function make(a,b){$("#"+a+"-total-paid").append("$"+b.totalPaid.toLocaleString()+" in "+getTimeString(b.months)),c3.generate({bindto:"#"+a+"-balance-chart",data:{x:"month",rows:b.balances,type:"spline"},axis:{x:{label:{text:"month",position:"outer-center"}},y:{label:{text:"dollars",position:"outer-middle"}}}}),c3.generate({bindto:"#"+a+"-account-chart",data:{x:"month",rows:b.accounts,type:"area-step"},axis:{x:{label:{text:"month",position:"outer-center"}},y:{label:{text:"number of debts",position:"outer-middle"}}},line:{step:{type:"step-after"}}})}$(document).ready(function(){$("#addRowButton").click(function(){var a=generateRow(new Debt("",0,0,0,0,"dollar"));$("#debt-table tbody").append(a)}),$("#removeRowButton").click(function(){$("#debt-table tbody tr").last().remove()});var a;if(hasKey("name")&&hasKey("balance")&&hasKey("rate")&&hasKey("minpayment"))a=getObjectArray(),a.forEach(function(a){$.extend(a,new DebtProto),a.name=decodeURIComponent(a.name.replace(/\+/g," ")),a.rate=a.rate/100,a.balance=parseInt(a.balance),"percent"===a.minpaymenttype?a.minpayment=a.minpayment/100:a.minpayment=parseInt(a.minpayment)});else{a=new Array;var b=new Debt("credit card 1",3e3,.13,.04,"percent"),c=new Debt("credit card 2",8e3,.16,.04,"percent");a=[b,c]}for(var d=0;d<a.length;d++){var e=a[d];$("#debt-table").append(generateRow(e))}var f=getResults(a);make("highest-rate",f.highestRate),make("lowest-balance",f.lowestBalance),make("just-payments",f.justPayments)});
<commit_msg>Update avalanche.min.js<commit_after>function DebtProto(){this.getMinPayment=function(){var a;return a="percent"===this.minpaymenttype?Math.max(Math.round(this.balance*this.minpayment),5):this.minpayment,Math.min(a,this.balance)},this.update=function(){return this.balance=this.balance*(1+this.rate/12),this.balance=Math.round(this.balance),this.pay(this.getMinPayment())},this.pay=function(a){var b=0;return this.balance=this.balance-a,this.balance<=0&&(b=-this.balance,this.balance=0,this.minpayment=0),b}}function Debt(a,b,c,d,e){this.name=a,this.balance=b,this.rate=c,this.minpayment=d,this.minpaymenttype=e,$.extend(this,new DebtProto)}function avalanche(a,b,c){var d=c-sumMinpayments(a);for(d+=payDebts(a);d>0;)if(a=getDebtsWithBalances(a),a.length>0){var e=b(a);d=e.pay(d)}else d=0}function payDebts(a){return a.reduce(function(a,b){return a+b.update()},0)}function getDebtsWithBalances(a){return a.filter(function(a){return a.balance>0})}function sumBalances(a){return a.reduce(function(a,b){return a+b.balance},0)}function sumMinpayments(a){return a.reduce(function(a,b){return a+b.getMinPayment()},0)}function totalAccounts(a){return a.reduce(function(a,b){return a+Math.min(b.balance,1)},0)}function lowestBalance(a){return a.reduce(function(a,b){return null==a?b:a.balance>b.balance?b:a.balance===b.balance&&a.rate<b.rate?b:a})}function highestRate(a){return a.reduce(function(a,b){return null==a?b:a.rateb.balance?b:a})}function usingMethod(a,b){for(var c=totalAccounts(a),d=sumMinpayments(a),e={balances:[["month","balance","minimum payment"],[0,sumBalances(a),sumMinpayments(a)]],accounts:[["month","number of debts"],[0,c]],totalPaid:0,months:0},f=1,g=sumBalances(a);g>0&&f<=500;g=sumBalances(a),f++){"undefined"!=typeof b?avalanche(a,b,d):payDebts(a),f%12===0&&e.balances.push([f,g,sumMinpayments(a)]);var h=totalAccounts(a);h!==c&&(e.accounts.push([f,h]),c=h),"undefined"!=typeof b?d<sumBalances(a)?e.totalPaid=e.totalPaid+d:e.totalPaid=e.totalPaid+sumBalances(a):e.totalPaid=e.totalPaid+sumMinpayments(a)}return e.balances.push([f,sumBalances(a),sumMinpayments(a)]),e.months=f,e}function getResults(a){var b=JSON.parse(JSON.stringify(a));b.forEach(function(a){$.extend(a,new DebtProto)});var c=JSON.parse(JSON.stringify(a));c.forEach(function(a){$.extend(a,new DebtProto)});var d=JSON.parse(JSON.stringify(a));d.forEach(function(a){$.extend(a,new DebtProto)});var e={highestRate:usingMethod(b,highestRate),lowestBalance:usingMethod(c,lowestBalance),justPayments:usingMethod(d)};return e}function getTimeString(a){var b=Math.floor(a/12),c=a-12*b;return b+" years "+c+" months"}function generateRow(a){var b="<input type='text' name='name' value='"+a.name+"' required />",c="$<input type='number' name='balance' class='input-dollar' min='0' value='"+a.balance+"' required />",d="<input type='number' name='rate' class='input-percent' min='0' max='100' step='0.01' value='"+100*a.rate+"' required />%",e="<input type='number' name='minpayment' min='0' value='";e+="percent"===a.minpaymenttype?100*a.minpayment:a.minpayment,e+="' required />";var f="<select name='minpaymenttype'><option value='dollar'"+("dollar"===a.minpaymenttype?" selected":"")+">dollar</option><option value='percent'"+("percent"===a.minpaymenttype?" selected":"")+">percent</option></select>",g="
"+b+"	"+c+"	"+d+"	"+e+"	"+f+"
";return g}function make(a,b){$("#"+a+"-total-paid").append("$"+b.totalPaid.toLocaleString()+" in "+getTimeString(b.months)),c3.generate({bindto:"#"+a+"-balance-chart",data:{x:"month",rows:b.balances,type:"spline"},axis:{x:{label:{text:"month",position:"outer-center"}},y:{label:{text:"dollars",position:"outer-middle"}}}}),c3.generate({bindto:"#"+a+"-account-chart",data:{x:"month",rows:b.accounts,type:"area-step"},axis:{x:{label:{text:"month",position:"outer-center"}},y:{label:{text:"number of debts",position:"outer-middle"}}},line:{step:{type:"step-after"}}})}$(document).ready(function(){$("#addRowButton").click(function(){var a=generateRow(new Debt("",0,0,0,0,"dollar"));$("#debt-table tbody").append(a)}),$("#removeRowButton").click(function(){$("#debt-table tbody tr").last().remove()});var a;if(hasKey("name")&&hasKey("balance")&&hasKey("rate")&&hasKey("minpayment"))a=getObjectArray(),a.forEach(function(a){$.extend(a,new DebtProto),a.name=decodeURIComponent(a.name.replace(/\+/g," ")),a.rate=a.rate/100,a.balance=parseInt(a.balance),"percent"===a.minpaymenttype?a.minpayment=a.minpayment/100:a.minpayment=parseInt(a.minpayment)});else{a=new Array;var b=new Debt("credit card 1",3e3,.13,.04,"percent"),c=new Debt("credit card 2",8e3,.16,.04,"percent");a=[b,c]}for(var d=0;d<a.length;d++){var e=a[d];$("#debt-table").append(generateRow(e))}var f=getResults(a);make("highest-rate",f.highestRate),make("lowest-balance",f.lowestBalance),make("just-payments",f.justPayments)});
<|endoftext|>


<commit_before>'use strict';

const ccxt = require ('ccxt')
    , {
        sleep,
        isNode,
        milliseconds,
    } = ccxt
    , Client = require ('./Client')
    , WebSocket = isNode ? require ('ws') : window.WebSocket

module.exports = class WsClient extends Client {

    createConnection () {
        if (this.verbose) {
            this.print (new Date (), 'connecting to', this.url)
        }
        this.connectionStarted = milliseconds ()
        this.setConnectionTimeout ()
        this.connection = new WebSocket (this.url, this.protocols, this.options)

        this.connection.onopen = this.onOpen.bind (this)
        this.connection.onmessage = this.onMessage.bind (this)
        this.connection.onerror = this.onError.bind (this)
        this.connection.onclose = this.onClose.bind (this)
        if (isNode) {
            this.connection
                .on ('ping', this.onPing.bind (this))
                .on ('pong', this.onPong.bind (this))
                .on ('upgrade', this.onUpgrade.bind (this))
        }
        // this.connection.terminate () // debugging
        // this.connection.close () // debugging
    }

    connect (backoffDelay = 0) {
        if (!this.startedConnecting) {
            // exponential backoff for consequent ws connections if necessary
            this.startedConnecting = true
            if (backoffDelay) {
                sleep (backoffDelay).then (this.createConnection.bind (this))
            } else {
                this.createConnection ()
            }
        }
        return this.connected
    }

    isOpen () {
        return (this.connection.readyState === WebSocket.OPEN)
    }

    close () {
        if (this.connection instanceof WebSocket) {
            return this.connection.close ()
        }
    }

}
<commit_msg>comment<commit_after>'use strict';

const ccxt = require ('ccxt')
    , {
        sleep,
        isNode,
        milliseconds,
    } = ccxt
    , Client = require ('./Client')
    , WebSocket = isNode ? require ('ws') : window.WebSocket

module.exports = class WsClient extends Client {

    createConnection () {
        if (this.verbose) {
            this.print (new Date (), 'connecting to', this.url)
        }
        this.connectionStarted = milliseconds ()
        this.setConnectionTimeout ()
        this.connection = new WebSocket (this.url, this.protocols, this.options)

        this.connection.onopen = this.onOpen.bind (this)
        this.connection.onmessage = this.onMessage.bind (this)
        this.connection.onerror = this.onError.bind (this)
        this.connection.onclose = this.onClose.bind (this)
        if (isNode) {
            this.connection
                .on ('ping', this.onPing.bind (this))
                .on ('pong', this.onPong.bind (this))
                .on ('upgrade', this.onUpgrade.bind (this))
        }
        // this.connection.terminate () // debugging
        // this.connection.close () // debugging
    }

    connect (backoffDelay = 0) {
        if (!this.startedConnecting) {
            this.startedConnecting = true
            // exponential backoff for consequent ws connections if necessary
            if (backoffDelay) {
                sleep (backoffDelay).then (this.createConnection.bind (this))
            } else {
                this.createConnection ()
            }
        }
        return this.connected
    }

    isOpen () {
        return (this.connection.readyState === WebSocket.OPEN)
    }

    close () {
        if (this.connection instanceof WebSocket) {
            return this.connection.close ()
        }
    }

}
<|endoftext|>


<commit_before>'use strict';

const ccxt = require ('ccxt')
    , {
        sleep,
        isNode,
        milliseconds,
    } = ccxt
    , Client = require ('./Client')
    , WebSocket = isNode ? require ('ws') : window.WebSocket

module.exports = class WsClient extends Client {

    createConnection () {
        console.log (new Date (), 'connecting...')
        this.connectionStarted = milliseconds ()
        this.setConnectionTimeout ()
        this.connection = new WebSocket (this.url, this.protocols, this.options)
        this.connection
            .on ('open', this.onOpen.bind (this))
            .on ('ping', this.onPing.bind (this))
            .on ('pong', this.onPong.bind (this))
            .on ('error', this.onError.bind (this))
            .on ('close', this.onClose.bind (this))
            .on ('upgrade', this.onUpgrade.bind (this))
            .on ('message', this.onMessage.bind (this))
        // this.connection.terminate () // debugging
        // this.connection.close () // debugging
    }

    connect (backoffDelay = 0) {
        if ((this.connection.readyState !== WebSocket.OPEN) && (this.connection.readyState !== WebSocket.CONNECTING)) {
            // prevent multiple calls overwriting each other
            this.connection.readyState = WebSocket.CONNECTING
            // exponential backoff for consequent ws connections if necessary
            if (backoffDelay) {
                sleep (backoffDelay).then (this.createConnection.bind (this))
            } else {
                this.createConnection ()
            }
        }
        return this.connected
    }

    isOpen () {
        return (this.connection.readyState === WebSocket.OPEN)
    }
}
<commit_msg>WsClient.js print url upon connecting<commit_after>'use strict';

const ccxt = require ('ccxt')
    , {
        sleep,
        isNode,
        milliseconds,
    } = ccxt
    , Client = require ('./Client')
    , WebSocket = isNode ? require ('ws') : window.WebSocket

module.exports = class WsClient extends Client {

    createConnection () {
        console.log (new Date (), 'connecting to', this.url)
        this.connectionStarted = milliseconds ()
        this.setConnectionTimeout ()
        this.connection = new WebSocket (this.url, this.protocols, this.options)
        this.connection
            .on ('open', this.onOpen.bind (this))
            .on ('ping', this.onPing.bind (this))
            .on ('pong', this.onPong.bind (this))
            .on ('error', this.onError.bind (this))
            .on ('close', this.onClose.bind (this))
            .on ('upgrade', this.onUpgrade.bind (this))
            .on ('message', this.onMessage.bind (this))
        // this.connection.terminate () // debugging
        // this.connection.close () // debugging
    }

    connect (backoffDelay = 0) {
        if ((this.connection.readyState !== WebSocket.OPEN) && (this.connection.readyState !== WebSocket.CONNECTING)) {
            // prevent multiple calls overwriting each other
            this.connection.readyState = WebSocket.CONNECTING
            // exponential backoff for consequent ws connections if necessary
            if (backoffDelay) {
                sleep (backoffDelay).then (this.createConnection.bind (this))
            } else {
                this.createConnection ()
            }
        }
        return this.connected
    }

    isOpen () {
        return (this.connection.readyState === WebSocket.OPEN)
    }
}
<|endoftext|>