<commit_before>(function () {
   var util = YAHOO.util, lang = YAHOO.lang, Event = YAHOO.util.Event, inputEx = YAHOO.inputEx, Dom = util.Dom;

/**
 * Create a group of fields within a FORM tag and adds buttons
 * @class inputEx.Form
 * @extends inputEx.Group
 * @constructor
 * @param {Object} options The following options are added for Forms:
 *

 *
buttons: list of button definition objects {value: 'Click Me', type: 'submit'}

 *
ajax: send the form through an ajax request (submit button should be present): {method: 'POST', uri: 'myScript.php', callback: same as YAHOO.util.Connect.asyncRequest callback}

 *
showMask: adds a mask over the form while the request is running (default is false)

 *

 */
inputEx.Form = function(options) {
   inputEx.Form.superclass.constructor.call(this, options);
};

lang.extend(inputEx.Form, inputEx.Group, {

   /**
    * Adds buttons and set ajax default parameters
    * @param {Object} options Options object (inputEx inputParams) as passed to the constructor
    */
   setOptions: function(options) {
      inputEx.Form.superclass.setOptions.call(this, options);

      this.buttons = [];

      this.options.buttons = options.buttons || [];

      this.options.action = options.action;
   	this.options.method = options.method;

		this.options.className =  options.className || 'inputEx-Group';
		this.options.autocomplete = lang.isUndefined(options.autocomplete) ? true : options.autocomplete;

      if(options.ajax) {
         this.options.ajax = {};
         this.options.ajax.method = options.ajax.method || 'POST';
         this.options.ajax.uri = options.ajax.uri || 'default.php';
         this.options.ajax.callback = options.ajax.callback || {};
         this.options.ajax.callback.scope = options.ajax.callback.scope || this;
         this.options.ajax.showMask = lang.isUndefined(options.ajax.showMask) ? false : options.ajax.showMask;

			this.options.ajax.contentType = options.ajax.contentType || "application/json";
			this.options.ajax.wrapObject = options.ajax.wrapObject;
      }

      if (lang.isFunction(options.onSubmit)) {
         this.options.onSubmit = options.onSubmit;
      }
   },

   /**
    * Render the group
    */
   render: function() {
      // Create the div wrapper for this group
  	   this.divEl = inputEx.cn('div', {className: this.options.className});
	   if(this.options.id) {
   	   this.divEl.id = this.options.id;
   	}

  	   // Create the FORM element
      this.form = inputEx.cn('form', {method: this.options.method || 'POST', action: this.options.action || '', className: this.options.className || 'inputEx-Form'});
      this.divEl.appendChild(this.form);

	   // Set the autocomplete attribute to off to disable firefox autocompletion
		if(!this.options.autocomplete) {
	   	this.form.setAttribute('autocomplete','off');
		}

      // Set the name of the form
      if(this.options.formName) { this.form.name = this.options.formName; }

  	   this.renderFields(this.form);

      this.renderButtons();

      if(this.options.disabled) {
  	      this.disable();
  	   }
   },

   /**
    * Render the buttons
    */
   renderButtons: function() {

      this.buttonDiv = inputEx.cn('div', {className: 'inputEx-Form-buttonBar'});

	   var button, buttonEl;
	   for(var i = 0 ; i < this.options.buttons.length ; i++ ) {
	      button = this.options.buttons[i];

			// Throw Error if button is undefined
			if(!button) {
				throw new Error("inputEx.Form: One of the provided button is undefined ! (check trailing comma)");
			}

	      buttonEl = inputEx.cn('input', {type: button.type, value: button.value});
	      if( button.onClick ) { buttonEl.onclick = button.onClick; }
	      this.buttons.push(buttonEl);
	      this.buttonDiv.appendChild(buttonEl);
	   }

	   this.form.appendChild(this.buttonDiv);
   },

   /**
    * Init the events
    */
   initEvents: function() {
      inputEx.Form.superclass.initEvents.call(this);

      // Handle the submit event
      Event.addListener(this.form, 'submit', this.options.onSubmit || this.onSubmit,this,true);
   },

   /**
    * Intercept the 'onsubmit' event and stop it if !validate
    * If the ajax option object is set, use YUI async Request to send the form
    * @param {Event} e The original onSubmit event
    */
   onSubmit: function(e) {

      // do nothing if does not validate
	   if ( !this.validate() ) {
		   Event.stopEvent(e); // no submit
		   return; // no ajax submit
	   }

	   if(this.options.ajax) {
		   Event.stopEvent(e);
	      this.asyncRequest();
	   }
   },

   /**
    * Send the form value in JSON through an ajax request
    */
   asyncRequest: function() {

      if(this.options.ajax.showMask) { this.showMask(); }

		var formValue = this.getValue();

		// options.ajax.uri and options.ajax.method can also be functions that return a the uri/method depending of the value of the form
		var uri = lang.isFunction(this.options.ajax.uri) ? this.options.ajax.uri(formValue) : this.options.ajax.uri;
		var method = lang.isFunction(this.options.ajax.method) ? this.options.ajax.method(formValue) : this.options.ajax.method;

		var postData = null;

		// Classic application/x-www-form-urlencoded (like html forms)
		if(this.options.ajax.contentType == "application/x-www-form-urlencoded" && method != "PUT") {
			var params = [];
			for(var key in formValue) {
				if(formValue.hasOwnProperty(key)) {
					var pName = (this.options.ajax.wrapObject ? this.options.ajax.wrapObject+'[' : '')+key+(this.options.ajax.wrapObject ? ']' : '');
					params.push( pName+"="+window.encodeURIComponent(formValue[key]));
				}
			}
			postData = params.join('&');
		}
		// The only other contentType available is "application/json"
		else {
			YAHOO.util.Connect.initHeader("Content-Type" , "application/json" , false);

			// method PUT don't send as x-www-form-urlencoded but in JSON
			if(method == "PUT") {
				var formVal = this.getValue();
				var p;
				if(this.options.ajax.wrapObject) {
					p = {};
					p[this.options.ajax.wrapObject] = formVal;
				}
				else {
					p = formVal;
				}
				postData = lang.JSON.stringify(p);
			}
			else {
				// We keep this case for backward compatibility, but should not be used
				// Used when we send in JSON in POST or GET
				postData = "value="+lang.JSON.stringify(this.getValue());
			}
		}

      util.Connect.asyncRequest( method, uri, {
         success: function(o) {
            if(this.options.ajax.showMask) { this.hideMask(); }
            if( lang.isFunction(this.options.ajax.callback.success) ) {
               this.options.ajax.callback.success.call(this.options.ajax.callback.scope,o);
            }
         },

         failure: function(o) {
            if(this.options.ajax.showMask) { this.hideMask(); }
            if( lang.isFunction(this.options.ajax.callback.failure) ) {
               this.options.ajax.callback.failure.call(this.options.ajax.callback.scope,o);
            }
         },

         scope:this
      }, postData);
   },

   /**
    * Create a Mask over the form
    */
   renderMask: function() {
      if(this.maskRendered) return;

      // position as "relative" to position formMask inside as "absolute"
      Dom.setStyle(this.divEl, "position", "relative");

      // set zoom = 1 to fix hasLayout issue with IE6/7
      if (YAHOO.env.ua.ie) { Dom.setStyle(this.divEl, "zoom", 1); }

      // Render mask over the divEl
      this.formMask = inputEx.cn('div', {className: 'inputEx-Form-Mask'},
         {
            display: 'none',
            // Use offsetWidth instead of Dom.getStyle(this.divEl,"width") because
            // would return "auto" with IE instead of size in px
            width: this.divEl.offsetWidth+"px",
            height: this.divEl.offsetHeight+"px"
         },
         "

"+inputEx.messages.ajaxWait+"
");
      this.divEl.appendChild(this.formMask);
      this.maskRendered = true;
   },

   /**
    * Show the form mask
    */
   showMask: function() {
      this.renderMask();

      // Hide selects in IE 6
      this.toggleSelectsInIE(false);

      this.formMask.style.display = '';
   },

   /**
    * Hide the form mask
    */
   hideMask: function() {

      // Show selects back in IE 6
      this.toggleSelectsInIE(true);

      this.formMask.style.display = 'none';
   },

   /*
   * Method to hide selects in IE 6 when masking the form (else they would appear over the mask)
   */
   toggleSelectsInIE: function(show) {
      // IE 6 only
      if (!!YAHOO.env.ua.ie && YAHOO.env.ua.ie < 7) {
         var method = !!show ? YAHOO.util.Dom.removeClass : YAHOO.util.Dom.addClass;
         var that = this;
         YAHOO.util.Dom.getElementsBy(
            function() {return true;},
            "select",
            this.divEl,
            function(el) {method.call(that,el,"inputEx-hidden");}
         );
      }
   },

   /**
    * Enable all fields and buttons in the form
    */
   enable: function() {
      inputEx.Form.superclass.enable.call(this);
      for (var i = 0 ; i < this.buttons.length ; i++) {
 	      this.buttons[i].disabled = false;
      }
   },

   /**
    * Disable all fields and buttons in the form
    */
   disable: function() {
      inputEx.Form.superclass.disable.call(this);
      for (var i = 0 ; i < this.buttons.length ; i++) {
 	      this.buttons[i].disabled = true;
      }
   }

});

// Specific waiting message in ajax submit
inputEx.messages.ajaxWait = "Please wait...";;

// Register this class as "form" type
inputEx.registerType("form", inputEx.Form, [
   {type: 'list', inputParams:{
      label: 'Buttons',
      name: 'buttons',
         elementType: {
            type: 'group',
            inputParams: {
               fields: [
                  { inputParams: {label: 'Label', name: 'value'}},
                  { type: 'select', inputParams: {label: 'Type', name: 'type', selectValues:["button", "submit"]} }
               ]
            }
         }
      }
   }
]);

})();
<commit_msg>encodeURIComponent on stringified value before submitting ajax form<commit_after>(function () {
   var util = YAHOO.util, lang = YAHOO.lang, Event = YAHOO.util.Event, inputEx = YAHOO.inputEx, Dom = util.Dom;

/**
 * Create a group of fields within a FORM tag and adds buttons
 * @class inputEx.Form
 * @extends inputEx.Group
 * @constructor
 * @param {Object} options The following options are added for Forms:
 *

 *
buttons: list of button definition objects {value: 'Click Me', type: 'submit'}

 *
ajax: send the form through an ajax request (submit button should be present): {method: 'POST', uri: 'myScript.php', callback: same as YAHOO.util.Connect.asyncRequest callback}

 *
showMask: adds a mask over the form while the request is running (default is false)

 *

 */
inputEx.Form = function(options) {
   inputEx.Form.superclass.constructor.call(this, options);
};

lang.extend(inputEx.Form, inputEx.Group, {

   /**
    * Adds buttons and set ajax default parameters
    * @param {Object} options Options object (inputEx inputParams) as passed to the constructor
    */
   setOptions: function(options) {
      inputEx.Form.superclass.setOptions.call(this, options);

      this.buttons = [];

      this.options.buttons = options.buttons || [];

      this.options.action = options.action;
   	this.options.method = options.method;

		this.options.className =  options.className || 'inputEx-Group';
		this.options.autocomplete = lang.isUndefined(options.autocomplete) ? true : options.autocomplete;

      if(options.ajax) {
         this.options.ajax = {};
         this.options.ajax.method = options.ajax.method || 'POST';
         this.options.ajax.uri = options.ajax.uri || 'default.php';
         this.options.ajax.callback = options.ajax.callback || {};
         this.options.ajax.callback.scope = options.ajax.callback.scope || this;
         this.options.ajax.showMask = lang.isUndefined(options.ajax.showMask) ? false : options.ajax.showMask;

			this.options.ajax.contentType = options.ajax.contentType || "application/json";
			this.options.ajax.wrapObject = options.ajax.wrapObject;
      }

      if (lang.isFunction(options.onSubmit)) {
         this.options.onSubmit = options.onSubmit;
      }
   },

   /**
    * Render the group
    */
   render: function() {
      // Create the div wrapper for this group
  	   this.divEl = inputEx.cn('div', {className: this.options.className});
	   if(this.options.id) {
   	   this.divEl.id = this.options.id;
   	}

  	   // Create the FORM element
      this.form = inputEx.cn('form', {method: this.options.method || 'POST', action: this.options.action || '', className: this.options.className || 'inputEx-Form'});
      this.divEl.appendChild(this.form);

	   // Set the autocomplete attribute to off to disable firefox autocompletion
		if(!this.options.autocomplete) {
	   	this.form.setAttribute('autocomplete','off');
		}

      // Set the name of the form
      if(this.options.formName) { this.form.name = this.options.formName; }

  	   this.renderFields(this.form);

      this.renderButtons();

      if(this.options.disabled) {
  	      this.disable();
  	   }
   },

   /**
    * Render the buttons
    */
   renderButtons: function() {

      this.buttonDiv = inputEx.cn('div', {className: 'inputEx-Form-buttonBar'});

	   var button, buttonEl;
	   for(var i = 0 ; i < this.options.buttons.length ; i++ ) {
	      button = this.options.buttons[i];

			// Throw Error if button is undefined
			if(!button) {
				throw new Error("inputEx.Form: One of the provided button is undefined ! (check trailing comma)");
			}

	      buttonEl = inputEx.cn('input', {type: button.type, value: button.value});
	      if( button.onClick ) { buttonEl.onclick = button.onClick; }
	      this.buttons.push(buttonEl);
	      this.buttonDiv.appendChild(buttonEl);
	   }

	   this.form.appendChild(this.buttonDiv);
   },

   /**
    * Init the events
    */
   initEvents: function() {
      inputEx.Form.superclass.initEvents.call(this);

      // Handle the submit event
      Event.addListener(this.form, 'submit', this.options.onSubmit || this.onSubmit,this,true);
   },

   /**
    * Intercept the 'onsubmit' event and stop it if !validate
    * If the ajax option object is set, use YUI async Request to send the form
    * @param {Event} e The original onSubmit event
    */
   onSubmit: function(e) {

      // do nothing if does not validate
	   if ( !this.validate() ) {
		   Event.stopEvent(e); // no submit
		   return; // no ajax submit
	   }

	   if(this.options.ajax) {
		   Event.stopEvent(e);
	      this.asyncRequest();
	   }
   },

   /**
    * Send the form value in JSON through an ajax request
    */
   asyncRequest: function() {

      if(this.options.ajax.showMask) { this.showMask(); }

		var formValue = this.getValue();

		// options.ajax.uri and options.ajax.method can also be functions that return a the uri/method depending of the value of the form
		var uri = lang.isFunction(this.options.ajax.uri) ? this.options.ajax.uri(formValue) : this.options.ajax.uri;
		var method = lang.isFunction(this.options.ajax.method) ? this.options.ajax.method(formValue) : this.options.ajax.method;

		var postData = null;

		// Classic application/x-www-form-urlencoded (like html forms)
		if(this.options.ajax.contentType == "application/x-www-form-urlencoded" && method != "PUT") {
			var params = [];
			for(var key in formValue) {
				if(formValue.hasOwnProperty(key)) {
					var pName = (this.options.ajax.wrapObject ? this.options.ajax.wrapObject+'[' : '')+key+(this.options.ajax.wrapObject ? ']' : '');
					params.push( pName+"="+window.encodeURIComponent(formValue[key]));
				}
			}
			postData = params.join('&');
		}
		// The only other contentType available is "application/json"
		else {
			YAHOO.util.Connect.initHeader("Content-Type" , "application/json" , false);

			// method PUT don't send as x-www-form-urlencoded but in JSON
			if(method == "PUT") {
				var formVal = this.getValue();
				var p;
				if(this.options.ajax.wrapObject) {
					p = {};
					p[this.options.ajax.wrapObject] = formVal;
				}
				else {
					p = formVal;
				}
				postData = lang.JSON.stringify(p);
			}
			else {
				// We keep this case for backward compatibility, but should not be used
				// Used when we send in JSON in POST or GET
				postData = "value="+window.encodeURIComponent(lang.JSON.stringify(this.getValue()));
			}
		}

      util.Connect.asyncRequest( method, uri, {
         success: function(o) {
            if(this.options.ajax.showMask) { this.hideMask(); }
            if( lang.isFunction(this.options.ajax.callback.success) ) {
               this.options.ajax.callback.success.call(this.options.ajax.callback.scope,o);
            }
         },

         failure: function(o) {
            if(this.options.ajax.showMask) { this.hideMask(); }
            if( lang.isFunction(this.options.ajax.callback.failure) ) {
               this.options.ajax.callback.failure.call(this.options.ajax.callback.scope,o);
            }
         },

         scope:this
      }, postData);
   },

   /**
    * Create a Mask over the form
    */
   renderMask: function() {
      if(this.maskRendered) return;

      // position as "relative" to position formMask inside as "absolute"
      Dom.setStyle(this.divEl, "position", "relative");

      // set zoom = 1 to fix hasLayout issue with IE6/7
      if (YAHOO.env.ua.ie) { Dom.setStyle(this.divEl, "zoom", 1); }

      // Render mask over the divEl
      this.formMask = inputEx.cn('div', {className: 'inputEx-Form-Mask'},
         {
            display: 'none',
            // Use offsetWidth instead of Dom.getStyle(this.divEl,"width") because
            // would return "auto" with IE instead of size in px
            width: this.divEl.offsetWidth+"px",
            height: this.divEl.offsetHeight+"px"
         },
         "

"+inputEx.messages.ajaxWait+"
");
      this.divEl.appendChild(this.formMask);
      this.maskRendered = true;
   },

   /**
    * Show the form mask
    */
   showMask: function() {
      this.renderMask();

      // Hide selects in IE 6
      this.toggleSelectsInIE(false);

      this.formMask.style.display = '';
   },

   /**
    * Hide the form mask
    */
   hideMask: function() {

      // Show selects back in IE 6
      this.toggleSelectsInIE(true);

      this.formMask.style.display = 'none';
   },

   /*
   * Method to hide selects in IE 6 when masking the form (else they would appear over the mask)
   */
   toggleSelectsInIE: function(show) {
      // IE 6 only
      if (!!YAHOO.env.ua.ie && YAHOO.env.ua.ie < 7) {
         var method = !!show ? YAHOO.util.Dom.removeClass : YAHOO.util.Dom.addClass;
         var that = this;
         YAHOO.util.Dom.getElementsBy(
            function() {return true;},
            "select",
            this.divEl,
            function(el) {method.call(that,el,"inputEx-hidden");}
         );
      }
   },

   /**
    * Enable all fields and buttons in the form
    */
   enable: function() {
      inputEx.Form.superclass.enable.call(this);
      for (var i = 0 ; i < this.buttons.length ; i++) {
 	      this.buttons[i].disabled = false;
      }
   },

   /**
    * Disable all fields and buttons in the form
    */
   disable: function() {
      inputEx.Form.superclass.disable.call(this);
      for (var i = 0 ; i < this.buttons.length ; i++) {
 	      this.buttons[i].disabled = true;
      }
   }

});

// Specific waiting message in ajax submit
inputEx.messages.ajaxWait = "Please wait...";;

// Register this class as "form" type
inputEx.registerType("form", inputEx.Form, [
   {type: 'list', inputParams:{
      label: 'Buttons',
      name: 'buttons',
         elementType: {
            type: 'group',
            inputParams: {
               fields: [
                  { inputParams: {label: 'Label', name: 'value'}},
                  { type: 'select', inputParams: {label: 'Type', name: 'type', selectValues:["button", "submit"]} }
               ]
            }
         }
      }
   }
]);

})();
<|endoftext|>


<commit_before>
    var create_type = 0;
    var interval = null;

    head(function(){

      $('div.geom_type span').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        if (!$(this).hasClass('selected')) {
          $('div.geom_type span').removeClass('selected');
          $(this).addClass('selected');
        }
      });

      $('div.geom_type span a').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $(this).parent().trigger('click');
      });

      //Create new table
      $('a.new_table').click(function(ev){
         stopPropagation(ev);
         resetUploadFile();
         if (!$(this).hasClass('disabled')) {
           $('div.create_window').show();
           $('div.mamufas').fadeIn();
           bindESC();
         }
      });

      $('div.select_file input#url_txt').focusin(function(){
         $(this).val('');
         $('div.create_window span.bottom input').removeClass('disabled');
 	    });

      $('div.select_file input#url_txt').focusout(function(){
   	    if ($(this).val() == ""){
       	  $(this).val('Insert a valid URL...');
           $('div.create_window span.bottom input').addClass('disabled');
   	    }else{
     	    $('div.create_window span.bottom input').removeClass('disabled');
   	    }
 	    });

      $('div.create_window ul li a').click(function(ev){
        stopPropagation(ev);
        create_type = $(this).closest('li').index();

        if (!$(this).parent().hasClass('selected') && !$(this).parent().hasClass('disabled') && !$(this).parent().is("span")) {
          $('div.create_window ul li').removeClass('selected');
          $(this).parent().addClass('selected');
        }

				if (($(this).closest('li').index()==1) || ($(this).closest('li').index()==2) && $('div.select_file input#url_txt').val() == "Insert a valid URL...") {
					$('div.create_window span.bottom input').addClass('disabled');
				} else {
					$('div.create_window span.bottom input').removeClass('disabled');
				}
      });

      $('span.file input').hover(function(ev){
        $('span.file a').addClass('hover');
        $(document).css('cursor','pointer');
      },function(ev){
        $('span.file a').removeClass('hover');
        $(document).css('cursor','default');
      });

      $('form#import_file').submit(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        if (!$('div.create_window span.bottom input').hasClass('disabled')) {
          if (create_type==0) {
            var geom_type = $('div.geom_type span.selected a').text().toLowerCase();

            if (geom_type=="point") {
              geom_type="point";
            } else if (geom_type=="polygon") {
              geom_type="multipolygon";
            } else {
              geom_type="multilinestring";
            }

            createNewToFinish(geom_type,'');
          } else if (create_type==2) {
						var url = $('div.select_file input#url_txt').val();
						if (isURL(url)) {
							$('div.error_url').stop().fadeOut();
							createNewToFinish('',url,true);
						} else {
							$('div.error_url').stop().fadeIn().delay(2000).fadeOut();;
						}
          }
        }
      });

      //Uploader for the modal window
      var uploader = new qq.FileUploader({
        element: document.getElementById('uploader'),
        action: '/upload',
        params: {},
        allowedExtensions: ['csv', 'xls', 'xlsx', 'zip', 'kml', 'geojson', 'json', 'ods', 'kmz', 'gpx'],
        sizeLimit: 0, // max size
        minSizeLimit: 0, // min size
        debug: false,
        onSubmit: function(id, fileName){
          $('div.create_window ul li:eq(0)').addClass('disabled');
          $('form input[type="submit"]').addClass('disabled');
          $('span.file').addClass('uploading');
        },
        onProgress: function(id, fileName, loaded, total){
          var percentage = loaded / total;
          $('span.progress').width((346*percentage)/1);
        },
        onComplete: function(id, fileName, responseJSON){
          createNewToFinish('',responseJSON.file_uri);
        },
        onCancel: function(id, fileName){},
        showMessage: function(message){
          $('div.select_file p').html(message);
          $('div.select_file p').addClass('error');
        }
      });

      //Uploader for the whole page (dashboard only)
      var hugeUploader = new qq.FileUploader({
      	element: document.getElementById('hugeUploader'),
      	action: '/upload',
      	params: {},
        allowedExtensions: ['csv', 'xls', 'xlsx', 'zip', 'kml', 'geojson', 'json', 'ods', 'kmz', 'gpx'],
      	sizeLimit: 0,
      	minSizeLimit: 0,
      	debug: false,

      	onSubmit: function(id, fileName){
        	resetUploadFile();
      		$('div.create_window ul li:eq(0)').addClass('disabled');
      		$('form input[type="submit"]').addClass('disabled');
      		$('span.file').addClass('uploading');
      		$('div.create_window ul li:eq(1) a').click();
          $('#hugeUploader').hide();
          $('div.create_window').show();
          $('div.mamufas').fadeIn();
          bindESC();
      	},
      	onProgress: function(id, fileName, loaded, total){
      		var percentage = loaded / total;
      		$('span.progress').width((346*percentage)/1);
      	},
      	onComplete: function(id, fileName, responseJSON){
      		createNewToFinish('',responseJSON.file_uri);
      		$('#hugeUploader').hide();
      	},
      	onCancel: function(id, fileName){},
      	showMessage: function(message){
      		 $('div.select_file p').html(message);
      		 $('div.select_file p').addClass('error');
      	}
      });
    });

    function resetUploadFile() {
      create_type = 0;
      $('div.create_window ul li:eq(0)').removeClass('disabled');
      $('div.create_window ul li').removeClass('selected');
      $('div.create_window ul li:eq(0)').addClass('selected');
      $('div.create_window div.inner_ form').show();
      $('div.create_window div.inner_ form').css('opacity',1);
      $('div.create_window div.inner_').css('border-color','#CCCCCC');
      $('div.create_window a.close_create').removeClass('last');
      $('div.create_window div.inner_').css('height','auto');
      $('div.create_window div.inner_ span.loading').hide();
      $('div.create_window div.inner_ span.loading').css('opacity',0);
      $('form input[type="submit"]').removeClass('disabled');
      $('span.file').removeClass('uploading');
      $('div.create_window div.inner_ span.loading').removeClass('error');
      $('span.file input[type="file"]').attr('value','');
      $('div.select_file span.file p').text('We support xls, csv, gpx, shp, zip, etc...');
      $('div.select_file span.file p').removeClass('error');
      $('span.progress').width(5);
      $('div.create_window ul li:eq(1)').removeClass('finished');
      $('div.create_window').removeClass('georeferencing');
      $('div.create_window div.inner_ span.loading p').html('It\'s not gonna be a lot of time. Just a few seconds, ok?');
      $('div.create_window div.inner_ span.loading h5').html('We are creating your table...');
      $('div.qq-upload-drop-area').hide();
    }

    function createNewToFinish (type,url,out) {
      $('div.create_window div.inner_').animate({borderColor:'#FFC209', height:'68px'},500);
      $('div.create_window div.inner_ form').animate({opacity:0},300,function(){
        $('div.create_window div.inner_ span.loading').show();
				$('div.create_window a.close_create').hide();
        $('div.create_window div.inner_ span.loading').animate({opacity:1},200, function(){
          var params = {}
          if (url!='') {
            if (!out) {
              params = {file:'http://'+window.location.host + url};
            } else {
              params = {file:url};
            }
          } else {
            params = {the_geom_type:type}
          }
          $.ajax({
            type: "POST",
            url: global_api_url+'tables/',
            data: params,
            headers: {'cartodbclient':true},
            success: function(data, textStatus, XMLHttpRequest) {
              window.location.href = "/tables/"+data.id;
            },
            error: function(e) {
							var json = $.parseJSON(e.responseText);
							if (json) {
                $('div.create_window div.inner_ span.loading p').html(json.raw_error +'

'+ json.hint);
                $('div.create_window div.inner_ span.loading h5').text(json.message);
							} else {
                $('div.create_window div.inner_ span.loading p').html('There has been an error, please contact us with a sample of your data if possible. Thanks!');
                $('div.create_window div.inner_ span.loading h5').text('Oops! Error');
							}
						  $('div.create_window div.inner_ span.loading').addClass('error');
							$('div.create_window a.close_create').show().addClass('last');
              $('div.create_window div.inner_').height($('div.create_window div.inner_ span.loading').height() + 30);
            }
          });
        });
      });
      setTimeout(function(){$('div.create_window a.close_create').addClass('last');},250);
    }

    function retryImportTable() {
      $('div.create_window a.close_create').show().removeClass('last');
      $('div.create_window div.inner_').animate({borderColor:'#CCCCCC', height:'254px'},500,function(){
        $('div.create_window div.inner_').css('height','auto');
      });
      $('div.create_window ul li:eq(0)').removeClass('disabled');
      $('form input[type="submit"]').removeClass('disabled');
      $('span.file').removeClass('uploading');
      $('div.create_window div.inner_ span.loading').animate({opacity:0},300,function(){
        $('div.create_window div.inner_ span.loading').hide();
        $('div.create_window div.inner_ span.loading').removeClass('error');
        $('div.create_window div.inner_ span.loading p').html('It\'s not gonna be a lot of time. Just a few seconds, ok?');
        $('div.create_window div.inner_ span.loading h5').html('We are creating your table...');
        $('div.create_window div.inner_ form').show();
        $('div.create_window div.inner_ form').animate({opacity:1},200);
        $('div.select_file p').text('We support xls, csv, gpx, shp, zip, etc...');
        $('div.select_file p').removeClass('error');
      });
    }

<commit_msg>close #388<commit_after>
    var create_type = 0;
    var interval = null;

    head(function(){

      $('div.geom_type span').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        if (!$(this).hasClass('selected')) {
          $('div.geom_type span').removeClass('selected');
          $(this).addClass('selected');
        }
      });

      $('div.geom_type span a').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $(this).parent().trigger('click');
      });

      //Create new table
      $('a.new_table').click(function(ev){
         stopPropagation(ev);
         resetUploadFile();
         if (!$(this).hasClass('disabled')) {
           $('div.create_window').show();
           $('div.mamufas').fadeIn();
           bindESC();
         }
      });

      $('div.select_file input#url_txt').focusin(function(){
         $(this).val('');
         $('div.create_window span.bottom input').removeClass('disabled');
 	    });

      $('div.select_file input#url_txt').focusout(function(){
   	    if ($(this).val() == ""){
       	  $(this).val('Insert a valid URL...');
           $('div.create_window span.bottom input').addClass('disabled');
   	    }else{
     	    $('div.create_window span.bottom input').removeClass('disabled');
   	    }
 	    });

      $('div.create_window ul li a').click(function(ev){
        stopPropagation(ev);
        create_type = $(this).closest('li').index();

        if (!$(this).parent().hasClass('selected') && !$(this).parent().hasClass('disabled') && !$(this).parent().is("span")) {
          $('div.create_window ul li').removeClass('selected');
          $(this).parent().addClass('selected');
        }

				if (($(this).closest('li').index()==1) || ($(this).closest('li').index()==2) && $('div.select_file input#url_txt').val() == "Insert a valid URL...") {
					$('div.create_window span.bottom input').addClass('disabled');
				} else {
					$('div.create_window span.bottom input').removeClass('disabled');
				}
      });

      $('span.file input').hover(function(ev){
        $('span.file a').addClass('hover');
        $(document).css('cursor','pointer');
      },function(ev){
        $('span.file a').removeClass('hover');
        $(document).css('cursor','default');
      });

      $('form#import_file').submit(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        if (!$('div.create_window span.bottom input').hasClass('disabled')) {
          if (create_type==0) {
            var geom_type = $('div.geom_type span.selected a').text().toLowerCase();

            if (geom_type=="point") {
              geom_type="point";
            } else if (geom_type=="polygon") {
              geom_type="multipolygon";
            } else {
              geom_type="multilinestring";
            }

            createNewToFinish(geom_type,'');
          } else if (create_type==2) {
						var url = $('div.select_file input#url_txt').val();
						if (isURL(url)) {
							$('div.error_url').stop().fadeOut();
							createNewToFinish('',url,true);
						} else {
							$('div.error_url').stop().fadeIn().delay(2000).fadeOut();;
						}
          }
        }
      });

      //Uploader for the modal window
      var uploader = new qq.FileUploader({
        element: document.getElementById('uploader'),
        action: '/upload',
        params: {},
        allowedExtensions: ['csv', 'xls', 'xlsx', 'zip', 'kml', 'geojson', 'json', 'ods', 'kmz', 'gpx'],
        sizeLimit: 0, // max size
        minSizeLimit: 0, // min size
        debug: false,
        onSubmit: function(id, fileName){
          $('div.create_window ul li:eq(0)').addClass('disabled');
          $('form input[type="submit"]').addClass('disabled');
          $('span.file').addClass('uploading');
        },
        onProgress: function(id, fileName, loaded, total){
          var percentage = loaded / total;
          $('span.progress').width((346*percentage)/1);
        },
        onComplete: function(id, fileName, responseJSON){
          createNewToFinish('',responseJSON.file_uri);
        },
        onCancel: function(id, fileName){},
        showMessage: function(message){
          $('div.select_file p').html(message);
          $('div.select_file p').addClass('error');
        }
      });

      //Uploader for the whole page (dashboard only)
      var hugeUploader = new qq.FileUploader({
      	element: document.getElementById('hugeUploader'),
      	action: '/upload',
      	params: {},
        allowedExtensions: ['csv', 'xls', 'xlsx', 'zip', 'kml', 'geojson', 'json', 'ods', 'kmz', 'gpx'],
      	sizeLimit: 0,
      	minSizeLimit: 0,
      	debug: false,

      	onSubmit: function(id, fileName){
        	resetUploadFile();
      		$('div.create_window ul li:eq(0)').addClass('disabled');
      		$('form input[type="submit"]').addClass('disabled');
      		$('span.file').addClass('uploading');
      		$('div.create_window ul li:eq(1) a').click();
          $('#hugeUploader').hide();
          $('div.create_window').show();
          $('div.mamufas').fadeIn();
          bindESC();
      	},
      	onProgress: function(id, fileName, loaded, total){
      		var percentage = loaded / total;
      		$('span.progress').width((346*percentage)/1);
      	},
      	onComplete: function(id, fileName, responseJSON){
      		createNewToFinish('',responseJSON.file_uri);
      		$('#hugeUploader').hide();
      	},
      	onCancel: function(id, fileName){},
      	showMessage: function(message){
          $('div.select_file p').html(message);
          $('div.select_file p').addClass('error');
          $('div.create_window ul li:eq(0)').addClass('disabled');
          $('form input[type="submit"]').addClass('disabled');
          $('div.create_window ul li:eq(1) a').click();
          $('#hugeUploader').hide();
          $('div.create_window').show();
          $('div.mamufas').fadeIn();
          bindESC();
      	}
      });
    });

    function resetUploadFile() {
      create_type = 0;
      $('div.select_file p').removeClass('error');
      $('div.create_window ul li:eq(0)').removeClass('disabled');
      $('div.create_window ul li').removeClass('selected');
      $('div.create_window ul li:eq(0)').addClass('selected');
      $('div.create_window div.inner_ form').show();
      $('div.create_window div.inner_ form').css('opacity',1);
      $('div.create_window div.inner_').css('border-color','#CCCCCC');
      $('div.create_window a.close_create').removeClass('last');
      $('div.create_window div.inner_').css('height','auto');
      $('div.create_window div.inner_ span.loading').hide();
      $('div.create_window div.inner_ span.loading').css('opacity',0);
      $('form input[type="submit"]').removeClass('disabled');
      $('span.file').removeClass('uploading');
      $('div.create_window div.inner_ span.loading').removeClass('error');
      $('span.file input[type="file"]').attr('value','');
      $('div.select_file span.file p').text('We support xls, csv, gpx, shp, zip, etc...');
      $('div.select_file span.file p').removeClass('error');
      $('span.progress').width(5);
      $('div.create_window ul li:eq(1)').removeClass('finished');
      $('div.create_window').removeClass('georeferencing');
      $('div.create_window div.inner_ span.loading p').html('It\'s not gonna be a lot of time. Just a few seconds, ok?');
      $('div.create_window div.inner_ span.loading h5').html('We are creating your table...');
      $('div.qq-upload-drop-area').hide();
    }

    function createNewToFinish (type,url,out) {
      $('div.create_window div.inner_').animate({borderColor:'#FFC209', height:'68px'},500);
      $('div.create_window div.inner_ form').animate({opacity:0},300,function(){
        $('div.create_window div.inner_ span.loading').show();
				$('div.create_window a.close_create').hide();
        $('div.create_window div.inner_ span.loading').animate({opacity:1},200, function(){
          var params = {}
          if (url!='') {
            if (!out) {
              params = {file:'http://'+window.location.host + url};
            } else {
              params = {file:url};
            }
          } else {
            params = {the_geom_type:type}
          }
          $.ajax({
            type: "POST",
            url: global_api_url+'tables/',
            data: params,
            headers: {'cartodbclient':true},
            success: function(data, textStatus, XMLHttpRequest) {
              window.location.href = "/tables/"+data.id;
            },
            error: function(e) {
							var json = $.parseJSON(e.responseText);
							if (json) {
                $('div.create_window div.inner_ span.loading p').html(json.raw_error +'

'+ json.hint);
                $('div.create_window div.inner_ span.loading h5').text(json.message);
							} else {
                $('div.create_window div.inner_ span.loading p').html('There has been an error, please contact us with a sample of your data if possible. Thanks!');
                $('div.create_window div.inner_ span.loading h5').text('Oops! Error');
							}
						  $('div.create_window div.inner_ span.loading').addClass('error');
							$('div.create_window a.close_create').show().addClass('last');
              $('div.create_window div.inner_').height($('div.create_window div.inner_ span.loading').height() + 30);
            }
          });
        });
      });
      setTimeout(function(){$('div.create_window a.close_create').addClass('last');},250);
    }

    function retryImportTable() {
      $('div.create_window a.close_create').show().removeClass('last');
      $('div.create_window div.inner_').animate({borderColor:'#CCCCCC', height:'254px'},500,function(){
        $('div.create_window div.inner_').css('height','auto');
      });
      $('div.create_window ul li:eq(0)').removeClass('disabled');
      $('form input[type="submit"]').removeClass('disabled');
      $('span.file').removeClass('uploading');
      $('div.create_window div.inner_ span.loading').animate({opacity:0},300,function(){
        $('div.create_window div.inner_ span.loading').hide();
        $('div.create_window div.inner_ span.loading').removeClass('error');
        $('div.create_window div.inner_ span.loading p').html('It\'s not gonna be a lot of time. Just a few seconds, ok?');
        $('div.create_window div.inner_ span.loading h5').html('We are creating your table...');
        $('div.create_window div.inner_ form').show();
        $('div.create_window div.inner_ form').animate({opacity:1},200);
        $('div.select_file p').text('We support xls, csv, gpx, shp, zip, etc...');
        $('div.select_file p').removeClass('error');
      });
    }

<|endoftext|>


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

/**
 * This grunt task checks out the shas for a project, as specified in a dependencies.json file in its top level.
 * This grunt task will not checkout the parent repo (the sim itself), only its dependencies.
 */
/* eslint-env node */
'use strict';

var assert = require( 'assert' );
var child_process = require( 'child_process' );

/**
 * @param grunt - the grunt instance
 * @param {string} repositoryName - name of the repository
 * @param {boolean} toMaster - whether master should be used, or dependencies.json shas should be used
 */
module.exports = function( grunt, repositoryName, toMaster ) {

  var exec = function( command, args, callback ) {
    child_process.exec( command, args, function( error, stdout, stderr ) {
      grunt.log.writeln( stdout );
      grunt.log.writeln( stderr );
      callback( error, stdout, stderr );
    } );
  };

  // This option should be used only by build-server, to indicate that the task was invoked from build-server.
  var buildServer = !!grunt.option( 'buildServer' );

  var dependencies = grunt.file.readJSON( ( buildServer ) ? '../chipper/js/build-server/tmp/dependencies.json' : 'dependencies.json' );
  var done = grunt.task.current.async();
  var numCheckedOut = 0;
  var dependenciesToCheckOut = Object.keys( dependencies ).filter( function( repository ) {
    return repository !== repositoryName && repository !== 'comment';
  } );

  var numToCheckOut = dependenciesToCheckOut.length;

  // Iterate through each dependency and check out the correct branch
  dependenciesToCheckOut.forEach( function( dependencyName ) {
    assert( dependencies[ dependencyName ].branch && dependencies[ dependencyName ].sha );

    grunt.log.writeln( 'Checking out dependency ' + dependencyName + ': ' + dependencies[ dependencyName ].branch + '@' + dependencies[ dependencyName ].sha );

    // To execute something from a different directory:
    // cp.exec( 'foocommand', { cwd: 'path/to/dir/' }, callback);
    // http://stackoverflow.com/questions/14026967/calling-child-process-exec-in-node-as-though-it-was-executed-in-a-specific-folde
    var command = 'git checkout ' + ( toMaster ? 'master' : dependencies[ dependencyName ].sha );
    exec( command, { cwd: '../' + dependencyName }, function( error1 ) {
      assert( !error1, 'error in ' + command + ' for repo ' + dependencyName );
      grunt.log.writeln( 'Finished checkout.' );
      numCheckedOut++;
      if ( numToCheckOut === numCheckedOut ) {
        pruneAndUpdate();
      }
    } );
  } );

  // npm prune and npm update in current repo and in chipper
  var pruneAndUpdateRepo = function( repo, callback ) {
    exec( 'npm prune', { cwd: '../' + repo }, function( error1 ) {
      assert( !error1, 'error in npm prune for repo ' + repo );
      grunt.log.writeln( 'Finished npm prune for repo ' + repo );
      exec( 'npm update', { cwd: '../' + repo }, function( error1 ) {
        assert( !error1, 'error in npm update for repo ' + repo );
        grunt.log.writeln( 'Finished npm update for repo ' + repo );
        callback();
      } );
    } );
  };
  var pruneAndUpdate = function() {
    pruneAndUpdateRepo( repositoryName, function() {
      pruneAndUpdateRepo( 'chipper', function() {
        done();
      } );
    } );
  };

};<commit_msg>styled and conventional code, https://github.com/phetsims/chipper/issues/542<commit_after>// Copyright 2013-2015, University of Colorado Boulder

/**
 * This grunt task checks out the shas for a project, as specified in a dependencies.json file in its top level.
 * This grunt task will not checkout the parent repo (the sim itself), only its dependencies.
 */
/* eslint-env node */
'use strict';

var assert = require( 'assert' );
var child_process = require( 'child_process' );

/**
 * @param grunt - the grunt instance
 * @param {string} repositoryName - name of the repository
 * @param {boolean} toMaster - whether master should be used, or dependencies.json shas should be used
 */
module.exports = function( grunt, repositoryName, toMaster ) {

  var exec = function( command, args, callback ) {
    child_process.exec( command, args, function( error, stdout, stderr ) {
      grunt.log.writeln( stdout );
      grunt.log.writeln( stderr );
      callback( error, stdout, stderr );
    } );
  };

  // This option should be used only by build-server, to indicate that the task was invoked from build-server.
  var buildServer = !!grunt.option( 'buildServer' );

  var dependencies = grunt.file.readJSON( ( buildServer ) ? '../chipper/js/build-server/tmp/dependencies.json' : 'dependencies.json' );
  var done = grunt.task.current.async();
  var numCheckedOut = 0;
  var dependenciesToCheckOut = Object.keys( dependencies ).filter( function( repository ) {
    return repository !== repositoryName && repository !== 'comment';
  } );

  var numToCheckOut = dependenciesToCheckOut.length;

  // Iterate through each dependency and check out the correct branch
  dependenciesToCheckOut.forEach( function( dependencyName ) {
    assert( dependencies[ dependencyName ].branch && dependencies[ dependencyName ].sha );

    grunt.log.writeln( 'Checking out dependency ' + dependencyName + ': ' + dependencies[ dependencyName ].branch + '@' + dependencies[ dependencyName ].sha );

    // To execute something from a different directory:
    // cp.exec( 'foocommand', { cwd: 'path/to/dir/' }, callback);
    // http://stackoverflow.com/questions/14026967/calling-child-process-exec-in-node-as-though-it-was-executed-in-a-specific-folder
    var command = 'git checkout ' + ( toMaster ? 'master' : dependencies[ dependencyName ].sha );
    exec( command, { cwd: '../' + dependencyName }, function( error1 ) {
      assert( !error1, 'error in ' + command + ' for repo ' + dependencyName );
      grunt.log.writeln( 'Finished checkout.' );
      numCheckedOut++;
      if ( numToCheckOut === numCheckedOut ) {
        pruneAndUpdate();
      }
    } );
  } );

  // npm prune and npm update in current repo and in chipper
  var pruneAndUpdateRepo = function( repo, callback ) {
    exec( 'npm prune', { cwd: '../' + repo }, function( error1 ) {
      assert( !error1, 'error in npm prune for repo ' + repo );
      grunt.log.writeln( 'Finished npm prune for repo ' + repo );
      exec( 'npm update', { cwd: '../' + repo }, function( error1 ) {
        assert( !error1, 'error in npm update for repo ' + repo );
        grunt.log.writeln( 'Finished npm update for repo ' + repo );
        callback();
      } );
    } );
  };
  var pruneAndUpdate = function() {
    pruneAndUpdateRepo( repositoryName, function() {
      pruneAndUpdateRepo( 'chipper', function() {
        done();
      } );
    } );
  };

};<|endoftext|>


<commit_before>import chai, { expect } from 'chai';
import fs from 'fs';
import chaiAsPromised from 'chai-as-promised';
import _ from 'underscore';
import log from 'apify-shared/log';
import 'babel-polyfill';
import { ENV_VARS } from '../build/constants';
import * as Apify from '../build/index';

chai.use(chaiAsPromised);

const shortSleep = (millis = 25) => new Promise(resolve => setTimeout(resolve, millis));

describe('PuppeteerPool', () => {
    let prevEnvHeadless;
    let logLevel;

    before(() => {
        logLevel = log.getLevel();
        log.setLevel(log.LEVELS.ERROR);
        prevEnvHeadless = process.env[ENV_VARS.HEADLESS];
        process.env[ENV_VARS.HEADLESS] = '1';
    });

    after(() => {
        log.setLevel(logLevel);
        process.env[ENV_VARS.HEADLESS] = prevEnvHeadless;
    });

    it('should work', async () => {
        process.env[ENV_VARS.PROXY_PASSWORD] = 'abc123';
        process.env[ENV_VARS.PROXY_HOSTNAME] = 'my.host.com';
        process.env[ENV_VARS.PROXY_PORT] = 123;

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 3,
            retireInstanceAfterRequestCount: 5,
        });
        const browsers = [];

        // Open 6 pages 3 in both browsers.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);

        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(pool.activeInstances[0].activePages).to.be.eql(3);
        expect(pool.activeInstances[0].totalPages).to.be.eql(3);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);

        // Close 2 pages in a first browser.
        await (await browsers[0]).close();
        await (await browsers[1]).close();
        await shortSleep();

        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(pool.activeInstances[0].activePages).to.be.eql(1);
        expect(pool.activeInstances[0].totalPages).to.be.eql(3);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);

        // Open two more pages in first browser so it reaches 5 and gets retired.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);
        expect(pool.retiredInstances[0].activePages).to.be.eql(3);
        expect(pool.retiredInstances[0].totalPages).to.be.eql(5);

        // Open one more page to see that 3rd browser gets started.
        browsers.push(pool.newPage());
        await Promise.all(browsers);

        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);
        expect(pool.activeInstances[2].activePages).to.be.eql(1);
        expect(pool.activeInstances[2].totalPages).to.be.eql(1);
        expect(pool.retiredInstances[0].activePages).to.be.eql(3);
        expect(pool.retiredInstances[0].totalPages).to.be.eql(5);

        // Kill the remaning 3 pages from the 1st browser to see that it gets closed.
        await (await browsers[2]).close();
        await (await browsers[6]).close();

        // @TODO for some reason it fails here:
        // await (await browsers[7]).close();
        // await shortSleep();
        // expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Cleanup everything.
        await pool.destroy();
        delete process.env[ENV_VARS.PROXY_PASSWORD];
        delete process.env[ENV_VARS.PROXY_HOSTNAME];
        delete process.env[ENV_VARS.PROXY_PORT];
    });

    it('kills hanging retired instances', async () => {
        process.env[ENV_VARS.PROXY_PASSWORD] = 'abc123';
        process.env[ENV_VARS.PROXY_HOSTNAME] = 'my.host.com';
        process.env[ENV_VARS.PROXY_PORT] = 123;

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 3,
            retireInstanceAfterRequestCount: 5,
            instanceKillerIntervalMillis: 1000,
            killInstanceAfterMillis: 500,
        });
        const browsers = [];

        // Open 3 pages.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Close 2.
        await (await browsers[0]).close();
        await (await browsers[1]).close();
        await shortSleep();
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Open 2 more so that the browser gets retired.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);

        // Check that it's retired.
        expect(_.values(pool.activeInstances).length).to.be.eql(0);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);
        expect(pool.retiredInstances[0].activePages).to.be.eql(3);
        expect(pool.retiredInstances[0].totalPages).to.be.eql(5);

        // Sleep and check that it has been killed.
        await shortSleep(2100);
        expect(_.values(pool.activeInstances).length).to.be.eql(0);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Cleanup everything.
        await pool.destroy();
        delete process.env[ENV_VARS.PROXY_PASSWORD];
        delete process.env[ENV_VARS.PROXY_HOSTNAME];
        delete process.env[ENV_VARS.PROXY_PORT];
    });

    it('retire manually', async () => {
        process.env[ENV_VARS.PROXY_PASSWORD] = 'abc123';
        process.env[ENV_VARS.PROXY_HOSTNAME] = 'my.host.com';
        process.env[ENV_VARS.PROXY_PORT] = 123;

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 1,
            abortInstanceAfterRequestCount: 5,
            instanceKillerIntervalMillis: 1000,
            killInstanceAfterMillis: 500,
        });
        const pages = [];

        // Open 3 pages.
        pages.push(pool.newPage());
        pages.push(pool.newPage());
        pages.push(pool.newPage());
        await Promise.all(pages);
        expect(_.values(pool.activeInstances).length).to.be.eql(3);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Retire 1.
        await pool.retire((await pages[0]).browser());
        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);

        // Retire 2.
        await pool.retire((await pages[1]).browser());
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(2);

        // Sleep and check that two have been killed.
        await shortSleep(2100);
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Cleanup everything.
        await pool.destroy();
        delete process.env[ENV_VARS.PROXY_PASSWORD];
        delete process.env[ENV_VARS.PROXY_HOSTNAME];
        delete process.env[ENV_VARS.PROXY_PORT];
    });

    it('works with one page per instance', async () => {
        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 1,
            retireInstanceAfterRequestCount: 1,
        });

        const page1 = await pool.newPage();
        await page1.goto('about:blank');
        const pid1 = page1.browser().process().pid;

        const page2 = await pool.newPage();
        await page2.goto('about:blank');
        const pid2 = page2.browser().process().pid;

        await page1.close();
        await page2.close();

        const page3 = await pool.newPage();
        await page3.goto('about:blank');
        const pid3 = page3.browser().process().pid;

        await page3.close();

        // Ensure we spawned 3 different processes
        expect(pid1).not.to.be.eql(pid2);
        expect(pid2).not.to.be.eql(pid3);
        expect(pid3).not.to.be.eql(pid1);

        // Cleanup everything.
        await pool.destroy();
    });

    it('supports recycleDiskCache option', async () => {
        const isMacOs = false; // process.platform === 'darwin';

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 1,
            retireInstanceAfterRequestCount: 1,
            recycleDiskCache: true,
            launchPuppeteerOptions: { headless: !isMacOs },
        });

        // log.setLevel(log.LEVELS.DEBUG);

        const url = 'https://www.wikipedia.org';

        const page1 = await pool.newPage();
        const dir1 = page1.browser().recycleDiskCacheDir;

        expect(fs.existsSync(dir1)).to.be.eql(true);

        // First time, nothing can come from disk cache
        let fromDiskCache1 = 0;
        page1.on('response', (response) => {
            if (response._fromDiskCache) fromDiskCache1++; // eslint-disable-line no-underscore-dangle
            // console.log(response._url + ": " + response.fromCache() + "/" + response._fromDiskCache);
        });

        const cookies1before = await page1.cookies(url);
        expect(cookies1before.length).to.be.eql(0);

        await page1.goto(url);

        expect(fromDiskCache1).to.be.eql(0);

        await Apify.utils.sleep(1000);

        const cookies1after = await page1.cookies();
        expect(cookies1after.length).to.be.at.least(1);

        await page1.close();

        // Wait for browser to close
        await Apify.utils.sleep(5000);

        // User directory must be the same
        const page2 = await pool.newPage();
        const dir2 = page2.browser().recycleDiskCacheDir;
        expect(dir1).to.be.eql(dir2);
        expect(fs.existsSync(dir2)).to.be.eql(true);

        // Ensure at least few assets are loaded from disk cache
        let fromDiskCache2 = 0;
        page2.on('response', (response) => {
            if (response._fromDiskCache) fromDiskCache2++; // eslint-disable-line no-underscore-dangle
        });

        const cookies2before = await page2.cookies(url);
        expect(cookies2before.length).to.be.eql(0);

        await page2.goto(url);

        const cookies2after = await page2.cookies(url);
        expect(cookies2after.length).to.be.at.least(1);

        // TODO: This only works in headful mode now, but must work all the time
        if (isMacOs) {
            expect(fromDiskCache2).to.be.at.least(1);
        }

        // Open third browser while second is still open, it should use a new cache directory
        const page3 = await pool.newPage();
        const dir3 = page3.browser().recycleDiskCacheDir;
        expect(dir3).not.to.be.eql(dir2);
        expect(fs.existsSync(dir3)).to.be.eql(true);

        await page2.close();

        // Cleanup everything.
        await pool.destroy();

        // Check cache dirs were deleted
        await Apify.utils.sleep(1000);
        expect(fs.existsSync(dir1)).to.be.eql(false);
        expect(fs.existsSync(dir3)).to.be.eql(false);
    });
});
<commit_msg>Updated comments in tests<commit_after>import chai, { expect } from 'chai';
import fs from 'fs';
import chaiAsPromised from 'chai-as-promised';
import _ from 'underscore';
import log from 'apify-shared/log';
import 'babel-polyfill';
import { ENV_VARS } from '../build/constants';
import * as Apify from '../build/index';

chai.use(chaiAsPromised);

const shortSleep = (millis = 25) => new Promise(resolve => setTimeout(resolve, millis));

describe('PuppeteerPool', () => {
    let prevEnvHeadless;
    let logLevel;

    before(() => {
        logLevel = log.getLevel();
        log.setLevel(log.LEVELS.ERROR);
        prevEnvHeadless = process.env[ENV_VARS.HEADLESS];
        process.env[ENV_VARS.HEADLESS] = '1';
    });

    after(() => {
        log.setLevel(logLevel);
        process.env[ENV_VARS.HEADLESS] = prevEnvHeadless;
    });

    it('should work', async () => {
        process.env[ENV_VARS.PROXY_PASSWORD] = 'abc123';
        process.env[ENV_VARS.PROXY_HOSTNAME] = 'my.host.com';
        process.env[ENV_VARS.PROXY_PORT] = 123;

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 3,
            retireInstanceAfterRequestCount: 5,
        });
        const browsers = [];

        // Open 6 pages 3 in both browsers.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);

        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(pool.activeInstances[0].activePages).to.be.eql(3);
        expect(pool.activeInstances[0].totalPages).to.be.eql(3);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);

        // Close 2 pages in a first browser.
        await (await browsers[0]).close();
        await (await browsers[1]).close();
        await shortSleep();

        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(pool.activeInstances[0].activePages).to.be.eql(1);
        expect(pool.activeInstances[0].totalPages).to.be.eql(3);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);

        // Open two more pages in first browser so it reaches 5 and gets retired.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);
        expect(pool.retiredInstances[0].activePages).to.be.eql(3);
        expect(pool.retiredInstances[0].totalPages).to.be.eql(5);

        // Open one more page to see that 3rd browser gets started.
        browsers.push(pool.newPage());
        await Promise.all(browsers);

        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);
        expect(pool.activeInstances[1].activePages).to.be.eql(3);
        expect(pool.activeInstances[1].totalPages).to.be.eql(3);
        expect(pool.activeInstances[2].activePages).to.be.eql(1);
        expect(pool.activeInstances[2].totalPages).to.be.eql(1);
        expect(pool.retiredInstances[0].activePages).to.be.eql(3);
        expect(pool.retiredInstances[0].totalPages).to.be.eql(5);

        // Kill the remaning 3 pages from the 1st browser to see that it gets closed.
        await (await browsers[2]).close();
        await (await browsers[6]).close();

        // @TODO for some reason it fails here:
        // await (await browsers[7]).close();
        // await shortSleep();
        // expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Cleanup everything.
        await pool.destroy();
        delete process.env[ENV_VARS.PROXY_PASSWORD];
        delete process.env[ENV_VARS.PROXY_HOSTNAME];
        delete process.env[ENV_VARS.PROXY_PORT];
    });

    it('kills hanging retired instances', async () => {
        process.env[ENV_VARS.PROXY_PASSWORD] = 'abc123';
        process.env[ENV_VARS.PROXY_HOSTNAME] = 'my.host.com';
        process.env[ENV_VARS.PROXY_PORT] = 123;

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 3,
            retireInstanceAfterRequestCount: 5,
            instanceKillerIntervalMillis: 1000,
            killInstanceAfterMillis: 500,
        });
        const browsers = [];

        // Open 3 pages.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Close 2.
        await (await browsers[0]).close();
        await (await browsers[1]).close();
        await shortSleep();
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Open 2 more so that the browser gets retired.
        browsers.push(pool.newPage());
        browsers.push(pool.newPage());
        await Promise.all(browsers);

        // Check that it's retired.
        expect(_.values(pool.activeInstances).length).to.be.eql(0);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);
        expect(pool.retiredInstances[0].activePages).to.be.eql(3);
        expect(pool.retiredInstances[0].totalPages).to.be.eql(5);

        // Sleep and check that it has been killed.
        await shortSleep(2100);
        expect(_.values(pool.activeInstances).length).to.be.eql(0);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Cleanup everything.
        await pool.destroy();
        delete process.env[ENV_VARS.PROXY_PASSWORD];
        delete process.env[ENV_VARS.PROXY_HOSTNAME];
        delete process.env[ENV_VARS.PROXY_PORT];
    });

    it('retire manually', async () => {
        process.env[ENV_VARS.PROXY_PASSWORD] = 'abc123';
        process.env[ENV_VARS.PROXY_HOSTNAME] = 'my.host.com';
        process.env[ENV_VARS.PROXY_PORT] = 123;

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 1,
            abortInstanceAfterRequestCount: 5,
            instanceKillerIntervalMillis: 1000,
            killInstanceAfterMillis: 500,
        });
        const pages = [];

        // Open 3 pages.
        pages.push(pool.newPage());
        pages.push(pool.newPage());
        pages.push(pool.newPage());
        await Promise.all(pages);
        expect(_.values(pool.activeInstances).length).to.be.eql(3);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Retire 1.
        await pool.retire((await pages[0]).browser());
        expect(_.values(pool.activeInstances).length).to.be.eql(2);
        expect(_.values(pool.retiredInstances).length).to.be.eql(1);

        // Retire 2.
        await pool.retire((await pages[1]).browser());
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(2);

        // Sleep and check that two have been killed.
        await shortSleep(2100);
        expect(_.values(pool.activeInstances).length).to.be.eql(1);
        expect(_.values(pool.retiredInstances).length).to.be.eql(0);

        // Cleanup everything.
        await pool.destroy();
        delete process.env[ENV_VARS.PROXY_PASSWORD];
        delete process.env[ENV_VARS.PROXY_HOSTNAME];
        delete process.env[ENV_VARS.PROXY_PORT];
    });

    it('works with one page per instance', async () => {
        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 1,
            retireInstanceAfterRequestCount: 1,
        });

        const page1 = await pool.newPage();
        await page1.goto('about:blank');
        const pid1 = page1.browser().process().pid;

        const page2 = await pool.newPage();
        await page2.goto('about:blank');
        const pid2 = page2.browser().process().pid;

        await page1.close();
        await page2.close();

        const page3 = await pool.newPage();
        await page3.goto('about:blank');
        const pid3 = page3.browser().process().pid;

        await page3.close();

        // Ensure we spawned 3 different processes
        expect(pid1).not.to.be.eql(pid2);
        expect(pid2).not.to.be.eql(pid3);
        expect(pid3).not.to.be.eql(pid1);

        // Cleanup everything.
        await pool.destroy();
    });

    it('supports recycleDiskCache option', async () => {
        const isMacOs = false; // process.platform === 'darwin';

        const pool = new Apify.PuppeteerPool({
            maxOpenPagesPerInstance: 1,
            retireInstanceAfterRequestCount: 1,
            recycleDiskCache: true,
            launchPuppeteerOptions: { headless: !isMacOs },
        });

        // log.setLevel(log.LEVELS.DEBUG);

        const url = 'https://www.wikipedia.org';

        const page1 = await pool.newPage();
        const dir1 = page1.browser().recycleDiskCacheDir;

        expect(fs.existsSync(dir1)).to.be.eql(true);

        // First time, nothing can come from disk cache
        let fromDiskCache1 = 0;
        page1.on('response', (response) => {
            if (response._fromDiskCache) fromDiskCache1++; // eslint-disable-line no-underscore-dangle
            // console.log(response._url + ": " + response.fromCache() + "/" + response._fromDiskCache);
        });

        const cookies1before = await page1.cookies(url);
        expect(cookies1before.length).to.be.eql(0);

        await page1.goto(url);

        expect(fromDiskCache1).to.be.eql(0);

        await Apify.utils.sleep(1000);

        const cookies1after = await page1.cookies();
        expect(cookies1after.length).to.be.at.least(1);

        await page1.close();

        // Wait for browser to close
        await Apify.utils.sleep(5000);

        // User directory must be the same
        const page2 = await pool.newPage();
        const dir2 = page2.browser().recycleDiskCacheDir;
        expect(dir1).to.be.eql(dir2);
        expect(fs.existsSync(dir2)).to.be.eql(true);

        // Ensure at least few assets are loaded from disk cache
        let fromDiskCache2 = 0;
        page2.on('response', (response) => {
            if (response._fromDiskCache) fromDiskCache2++; // eslint-disable-line no-underscore-dangle
        });

        const cookies2before = await page2.cookies(url);
        expect(cookies2before.length).to.be.eql(0);

        await page2.goto(url);

        const cookies2after = await page2.cookies(url);
        expect(cookies2after.length).to.be.at.least(1);

        // TODO: This only works in headful mode now, but must work all the time
        // See https://bugs.chromium.org/p/chromium/issues/detail?id=882431
        if (isMacOs) {
            expect(fromDiskCache2).to.be.at.least(1);
        }

        // Open third browser while second is still open, it should use a new cache directory
        const page3 = await pool.newPage();
        const dir3 = page3.browser().recycleDiskCacheDir;
        expect(dir3).not.to.be.eql(dir2);
        expect(fs.existsSync(dir3)).to.be.eql(true);

        await page2.close();

        // Cleanup everything.
        await pool.destroy();

        // Check cache dirs were deleted
        await Apify.utils.sleep(1000);
        expect(fs.existsSync(dir1)).to.be.eql(false);
        expect(fs.existsSync(dir3)).to.be.eql(false);
    });
});
<|endoftext|>


<commit_before>// Include needed files
var fluffbot = require('../lib/fluffbot')
var discord = require('discord.js')
var event = require('../lib/event')

// Instantiate bots
var fluffbot = new fluffbot()
discord = new discord.Client()

discord.loginWithToken(fluffbot.settings.bot_token)

// Initiate the playing game to say the current version
discord.on('ready', function(event) {
	this.setPlayingGame('Alpha v1.0')
})

// Event listener when bot is added to a server
discord.on('serverCreated', function(server) {
	this.sendMessage(server.generalChannel ,'@everyone FluffBot has joined '+server.name+' and is here to help!');
})

// Event listener for new member joining
discord.on('serverNewMember', function(server, user) {
	this.sendMessage(server.generalChannel ,'@everyone Welcome '+user.toString()+' to the Fam');
})

// Event listener for member being removed
discord.on('serverMemberRemoved', function(server, user) {
	this.sendMessage(server.generalChannel ,'@everyone '+user.toString()+' was removed');
})

// Event listener registered
event.bus.on('response', function(message, data) {
	discord.startTyping(message)
	discord.reply(message, data)
	discord.stopTyping(message)
})

// Message event listener
discord.on('message', function(message) {

	if (message.content.indexOf('!') > -1 && message.content[0] == '!') {
		fluffbot._runCommand(message)
	}

})
<commit_msg>Added new event listener<commit_after>// Include needed files
var fluffbot = require('../lib/fluffbot')
var discord = require('discord.js')
var event = require('../lib/event')

// Instantiate bots
var fluffbot = new fluffbot()
discord = new discord.Client()

discord.loginWithToken(fluffbot.settings.bot_token)

// Initiate the playing game to say the current version
discord.on('ready', function(event) {
	this.setPlayingGame('Alpha v1.0')
})

// Event listener when bot is added to a server
discord.on('serverCreated', function(server) {
	this.sendMessage(server.generalChannel ,'@everyone FluffBot has joined '+server.name+' and is here to help!');
})

// Event listener for new member joining
discord.on('serverNewMember', function(server, user) {
	this.sendMessage(server.generalChannel ,'@everyone Welcome '+user.toString()+' to the Fam');
})

// Event listener for member being removed
discord.on('serverMemberRemoved', function(server, user) {
	this.sendMessage(server.generalChannel ,'@everyone '+user.toString()+' was removed');
})

// Event listener registered
event.bus.on('response', function(message, data) {
	discord.reply(message, data)
})

// Event listener registered
event.bus.on('message', function(message, data) {
	discord.sendMessage(message, data)
})

// Message event listener
discord.on('message', function(message) {

	if (message.content.indexOf('!') > -1 && message.content[0] == '!') {
		fluffbot._runCommand(message)
	}

})
<|endoftext|>


<commit_before>/**
 * Simple script to illustrate TDD.  Downloads a 2mb file.
 *
 * Created by tim on 8/9/14.
 */

var https= require('https');
var fs= require('fs');
var q= require('q');

function download2mbModule(fileName){
    function download2mbPromise(resolve){
        // tf - remember to end streams created in event loop code.
        var fileOut= fs.createWriteStream(fileName);
        var fileRequest= {
            host: 'raw.githubusercontent.com',
            path: '/timfulmer/node.dtla-tdd/master/lib/2mb/2mb'
        };
        function requestCallback(response){
            // tf - end:false give us a chance to hook into
            //  the end event.
            response.pipe(fileOut,{end: false});
            response.on('end', function(){
                // tf - always call end on any streams created.
                fileOut.end();
                resolve();
            });
        }
        var request= https.request(fileRequest,requestCallback);
        request.end();
    }
    return q.Promise(download2mbPromise);
}

exports=module.exports={download2mb:download2mbModule};<commit_msg>Some final touches.<commit_after>/**
 * Simple script to illustrate TDD.  Downloads a 2mb file.
 *
 * Created by tim on 8/9/14.
 */

var https= require('https');
var fs= require('fs');
var q= require('q');

function download2mbModule(fileName){
    function download2mbPromise(resolve){
        // tf - remember to end streams created in code.
        var fileOut= fs.createWriteStream(fileName);
        var fileRequest= {
            host: 'raw.githubusercontent.com',
            path: '/timfulmer/node.dtla-tdd/master/lib/2mb/2mb'
        };
        function requestCallback(response){
            // tf - end:false give us a chance to hook into
            //  the end event.
            response.pipe(fileOut,{end: false});
            response.on('end', function(){
                // tf - always call end on any streams created.
                fileOut.end();
                resolve();
            });
        }
        var request= https.request(fileRequest,requestCallback);
        request.end();
    }
    return q.Promise(download2mbPromise);
}

exports=module.exports={download2mb:download2mbModule};<|endoftext|>


<commit_before>
module.exports = {

  assign:        require('lodash.assign'),
  isString:      function(value) { return typeof value === 'string' || value instanceof String },
  isPlainObject: require('lodash.isplainobject'),
  isNumber:      function(value) { return !isNaN(parseFloat(value)) && isFinite(value) },
  get:           require('lodash.get'),
  isNil:         function(value) { return value == null },
  pick:          require('lodash.pick'),
  last:          require('lodash.last'),
  isFunction:    require('lodash.isfunction'),
  defaultTo:     require('lodash.defaultto')
}
<commit_msg>replaced lodash assign with smaller version<commit_after>

function getprop(object, path, defaultVal) {
  var _path = Array.isArray(path) ? path : path.replace(/(\[(\d)\])/g, '.$2').split('.').filter(function(i) { return i.length })
  if (!_path.length) {
    return object === undefined ? defaultVal : object
  }
  return getprop(object[_path.shift()], _path, defaultVal)
}

function assign(target, options) {
  var args = Array.from(arguments)
  args.shift()
  for (var i = 0; i < args.length; ++i) {
    for (var prop in args[i]) {
      if (args[i].hasOwnProperty(prop)) {
        target[prop] = args[i][prop]
      }
    }
  }
  return target
}

module.exports = {
  assign:        assign,
  isString:      function(value) { return typeof value === 'string' || value instanceof String },
  isPlainObject: require('lodash.isplainobject'),
  isNumber:      function(value) { return !isNaN(parseFloat(value)) && isFinite(value) },
  isNil:         function(value) { return value == null },
  pick:          require('lodash.pick'),
  last:          require('lodash.last'),
  isFunction:    require('lodash.isfunction'),
  defaultTo:     require('lodash.defaultto'),
  get:           getprop
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Last.fm bidi
// @namespace   https://github.com/reith/hemianopsia
// @description This script rearranges right-to-left written texts
// @include     http://www.last.fm/*
// @include     http://www.lastfm.tld/*
// @require     https://raw.github.com/reith/hemianopsia/master/core.js
// @downloadURL https://raw.github.com/reith/hemianopsia/master/script/lastfm.user.js
// @run-at      document-end
// ==/UserScript==

(function() {
	if (window.top != window.self) return;

	var manifest = [
		{
			selector: '#content div.journals div.journalBody div.bbcode',
			comment: 'journal text'
		}, {
			selector: 'div.shoutboxContainer ul.shouts li.clearit p',
			root_selector: 'div#content > div.leftCol > div.leftColWrapper > div.deferred',
			live: true,
			comment: 'shoutbox in user and group profile'
		}, {
			selector: '#content div.fullWidth div.skylineRight div.skyWrap div#shoutbox ul#shoutList.shouts li.clearit p',
			comment: 'paged shoutbox'
		}, {
			selector: 'div.shoutboxContainer ul.shouts li.clearit p',
			root_selector: 'body.r-artist > div.page-wrapper > article.content > div.artist-social > section > div.deferred',
			live: true,
			comment: 'shoutbox in artist page'
		}, {
			selector: '#content div.journals div#shoutbox ul#shoutList.shouts li.clearit p',
			comment: 'journal comments'
		}
	];

	prepare_style();
	(new Bidier()).run(manifest);
})();
<commit_msg>last.fm: seperate rules by URL<commit_after>// ==UserScript==
// @name        Last.fm bidi
// @namespace   https://github.com/reith/hemianopsia
// @description This script rearranges right-to-left written texts
// @include     http://www.last.fm/*
// @include     http://www.lastfm.tld/*
// @require     https://raw.github.com/reith/hemianopsia/master/core.js
// @downloadURL https://raw.github.com/reith/hemianopsia/master/script/lastfm.user.js
// @grant       none
// @version     1.1
// @run-at      document-end
// ==/UserScript==

(function() {
	if (window.top != window.self) return;
	var manifest = [
		{
			path_re: /^\/user\/[^\/]+\/journal/,
			selector: '#content div.journals div.journalBody div.bbcode',
			comment: 'journal text'
		}, {
			path_re: /shoutbox$/,
			selector: '#content div.fullWidth div.skylineRight div.skyWrap div#shoutbox ul#shoutList.shouts li.clearit p',
			comment: 'paged shoutbox'
		}, {
			path_re: /^\/user\/[^\/]+\/journal/,
			comment: 'journal comments'
		}, {
			path_re: [
				/^\/music\/[^\/]+\//,
				/^\/user\/[^\/]+$/,
				/^\/group\/[^\/]+$/,
				/^\/music\/[^\/]+$/
			],
			root_selector: 'div.deferred',
			selector: 'div.shoutboxContainer ul.shouts li p',
			live: true,
			comment: 'in-page shoutbox'
		}
	];

	prepare_style();
	(new Bidier()).run(manifest);
})();
<|endoftext|>


<commit_before>/*jslint browser:true */

var meshpath = (function () {
    "use strict";

    var G, NORMAL_COLOR, SOURCE_COLOR, DEST_COLOR, NEIGHBOR_COLOR, DEFAULT_RADIUS;

    NORMAL_COLOR = '#0000ff';
    SOURCE_COLOR = '#00ff00';
    DEST_COLOR   = '#ff0000';
    NEIGHBOR_COLOR = '#ff8000';
    DEFAULT_RADIUS = 25;

    function Point(x, y, color, radius) {
        this.x = x;
        this.y = y;
        this.color = color === undefined ? NORMAL_COLOR : color;
        this.radius = radius === undefined ? DEFAULT_RADIUS : radius;

        this.squared_distance_from = function (pt) {
            return ((x - pt.x) * (x - pt.x)) + ((y - pt.y) * (y - pt.y));
        };

        this.distance_from = function (pt) {
            return Math.sqrt(this.squared_distance_from(pt));
        };

        this.toString = function () {
            return '(' + this.x + ',' + this.y + ')';
        };
    }

    function randomIntRange(lower_bound, upper_bound) {
        return Math.floor((Math.random() * (upper_bound - lower_bound + 1)) + lower_bound);
    }

    function randomPoint(xrange, yrange) {
        return new Point(randomIntRange(0, xrange), randomIntRange(0, yrange));
    }

    function QuadTree(pt) {
        this.NW = null;
        this.NE = null;
        this.SW = null;
        this.SE = null;

        this.pt = pt;

        this.insert = function (pt) {
            if (this.pt.squared_distance_from(pt) !== 0) {
                if (pt.x > this.pt.x) {
                    if (pt.y > this.pt.y) {
                        if (this.NE) {
                            this.NE.insert(pt);
                        } else {
                            this.NE = new QuadTree(pt);
                        }
                    } else {
                        if (this.SE) {
                            this.SE.insert(pt);
                        } else {
                            this.SE = new QuadTree(pt);
                        }
                    }
                } else {
                    if (pt.y > this.pt.y) {
                        if (this.NW) {
                            this.NW.insert(pt);
                        } else {
                            this.NW = new QuadTree(pt);
                        }
                    } else {
                        if (this.SW) {
                            this.SW.insert(pt);
                        } else {
                            this.SW = new QuadTree(pt);
                        }
                    }
                }
            // } else {
                // Duplicates silently dropped!
                // Doug hates empty blocks!
            }
        };

        this.depth_first_traversal = function (fn) {
            if (this.NW) {
                this.NW.depth_first_traversal(fn);
            }
            if (this.NE) {
                this.NE.depth_first_traversal(fn);
            }
            if (this.SW) {
                this.SW.depth_first_traversal(fn);
            }
            if (this.SE) {
                this.SE.depth_first_traversal(fn);
            }
            if (this.pt) {
                return fn(this.pt);
            }
        };

        this.nearest_neighbor = function (pt) {
            var min, tmp;

            min = { 'best': this.pt.squared_distance_from(pt), 'qt': this };

            if (this.NW) {
                tmp = this.NW.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            if (this.NE) {
                tmp = this.NE.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            if (this.SW) {
                tmp = this.SW.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            if (this.SE) {
                tmp = this.SE.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            return min;
        };
    }

    function get_neighbors_in_radius(qt, pt, radius) {
        var neighborhood = [];

        if (qt) {
            if (qt.pt.squared_distance_from(pt) < radius * radius) {
                neighborhood.push(qt);
            }

            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.NW, pt, radius));
            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.NE, pt, radius));
            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.SW, pt, radius));
            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.SE, pt, radius));
        }

        return neighborhood;
    }

    function plot_point(pt) {
        G.ctx.beginPath();
        G.ctx.arc(pt.x, pt.y, 3, 2 * Math.PI, false);
        G.ctx.fillStyle = pt.color;
        G.ctx.fill();
    }

    function highlight_neighbors(pt, color, radius) {
        var neighbors, i;
        neighbors = get_neighbors_in_radius(G.quadtree, pt, radius === undefined ? pt.radius : radius);
        for (i = 0; i < neighbors.length; i += 1) {
            neighbors[i].pt.color = color === undefined ? NEIGHBOR_COLOR : color;
            plot_point(neighbors[i].pt);
        }
    }

    function canvas_click(e) {
        if (G.quadtree) {
            var coords, closest_point;

            coords = G.canvas.relMouseCoords(e);
            closest_point = G.quadtree.nearest_neighbor(new Point(coords.x, coords.y));

            if (closest_point.qt === G.src) {
                highlight_neighbors(G.src.pt, NORMAL_COLOR);
                G.src = null;
                closest_point.qt.pt.color = NORMAL_COLOR;
                G.src_node.innerHTML = '(none)';
            } else if (closest_point.qt === G.dst) {
                highlight_neighbors(G.dst.pt, NORMAL_COLOR);
                G.dst = null;
                closest_point.qt.pt.color = NORMAL_COLOR;
                G.dst_node.innerHTML = '(none)';
            } else if (null === G.src) {
                G.src = closest_point.qt;
                highlight_neighbors(G.src.pt, NEIGHBOR_COLOR);
                G.src.pt.color = SOURCE_COLOR;
                G.src_node.innerHTML = G.src.pt.toString();
            } else if (null === G.dst) {
                G.dst = closest_point.qt;
                highlight_neighbors(G.dst.pt, NEIGHBOR_COLOR);
                G.dst.pt.color = DEST_COLOR;
                G.dst_node.innerHTML = G.dst.pt.toString();
            } else {
                G.dst.pt.color = NORMAL_COLOR;
                highlight_neighbors(G.dst.pt, NORMAL_COLOR);
                plot_point(G.dst.pt);
                G.dst = closest_point.qt;
                highlight_neighbors(G.dst.pt, NEIGHBOR_COLOR);
                G.dst_node.innerHTML = G.dst.pt.toString();
                G.dst.pt.color = DEST_COLOR;
            }

            plot_point(closest_point.qt.pt);
        }
    }

    function create_canvas(width, height) {
        var canvas = document.createElement('canvas');
        canvas.setAttribute('id', 'map');
        canvas.setAttribute('width', width);
        canvas.setAttribute('height', height);
        canvas.addEventListener('click', function (e) { canvas_click(e); }, false);
        return canvas;
    }

    function init(x_dimension, y_dimension) {
        G = {};
        G.width = x_dimension;
        G.height = y_dimension;
        G.canvas = create_canvas(G.width, G.height);
        G.ctx = G.canvas.getContext('2d');
        document.getElementById('canvas_container').appendChild(G.canvas);
        G.quadtree = null;
        G.pixel = G.ctx.createImageData(1, 1).data;
        G.src = G.dst = null;
        G.src_node = document.getElementById('src');
        G.dst_node = document.getElementById('dst');
    }

    function draw_quadtree(qt) {
        qt.depth_first_traversal(plot_point);
    }

    function create_nodes(count) {
        var i = 0;

        if (!G.quadtree && count > 0) {
            G.quadtree = new QuadTree(randomPoint(G.width, G.height));
            i = 1;
        }

        for (i; i < count; i += 1) {
            G.quadtree.insert(randomPoint(G.width, G.height));
        }

        if (G.quadtree) {
            draw_quadtree(G.quadtree);
        }
    }

    function wagumba() {
    }

    return { 'init': init, 'create_nodes': create_nodes, 'wagumba': wagumba };
}());
<commit_msg>each node gets a GUID<commit_after>/*jslint browser:true */

var meshpath = (function () {
    "use strict";

    var G, NORMAL_COLOR, SOURCE_COLOR, DEST_COLOR, NEIGHBOR_COLOR, DEFAULT_RADIUS;

    NORMAL_COLOR = '#0000ff';
    SOURCE_COLOR = '#00ff00';
    DEST_COLOR   = '#ff0000';
    NEIGHBOR_COLOR = '#ff8000';
    DEFAULT_RADIUS = 25;

    function Point(x, y, color, radius) {
        this.x = x;
        this.y = y;
        this.color = color === undefined ? NORMAL_COLOR : color;
        this.radius = radius === undefined ? DEFAULT_RADIUS : radius;

        this.squared_distance_from = function (pt) {
            return ((x - pt.x) * (x - pt.x)) + ((y - pt.y) * (y - pt.y));
        };

        this.distance_from = function (pt) {
            return Math.sqrt(this.squared_distance_from(pt));
        };

        this.toString = function () {
            return '(' + this.x + ',' + this.y + ')';
        };
    }

    function randomIntRange(lower_bound, upper_bound) {
        return Math.floor((Math.random() * (upper_bound - lower_bound + 1)) + lower_bound);
    }

    function randomPoint(xrange, yrange) {
        return new Point(randomIntRange(0, xrange), randomIntRange(0, yrange));
    }

    function QuadTree(pt) {
        this.NW = null;
        this.NE = null;
        this.SW = null;
        this.SE = null;

        this.pt = pt;

        this.guid = guid();

        this.toString = function () {
            return this.pt.toString() + ':' + this.guid;
        };

        this.insert = function (pt) {
            if (this.pt.squared_distance_from(pt) !== 0) {
                if (pt.x > this.pt.x) {
                    if (pt.y > this.pt.y) {
                        if (this.NE) {
                            this.NE.insert(pt);
                        } else {
                            this.NE = new QuadTree(pt);
                        }
                    } else {
                        if (this.SE) {
                            this.SE.insert(pt);
                        } else {
                            this.SE = new QuadTree(pt);
                        }
                    }
                } else {
                    if (pt.y > this.pt.y) {
                        if (this.NW) {
                            this.NW.insert(pt);
                        } else {
                            this.NW = new QuadTree(pt);
                        }
                    } else {
                        if (this.SW) {
                            this.SW.insert(pt);
                        } else {
                            this.SW = new QuadTree(pt);
                        }
                    }
                }
            // } else {
                // Duplicates silently dropped!
                // Doug hates empty blocks!
            }
        };

        this.depth_first_traversal = function (fn) {
            if (this.NW) {
                this.NW.depth_first_traversal(fn);
            }
            if (this.NE) {
                this.NE.depth_first_traversal(fn);
            }
            if (this.SW) {
                this.SW.depth_first_traversal(fn);
            }
            if (this.SE) {
                this.SE.depth_first_traversal(fn);
            }
            if (this.pt) {
                return fn(this.pt);
            }
        };

        this.nearest_neighbor = function (pt) {
            var min, tmp;

            min = { 'best': this.pt.squared_distance_from(pt), 'qt': this };

            if (this.NW) {
                tmp = this.NW.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            if (this.NE) {
                tmp = this.NE.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            if (this.SW) {
                tmp = this.SW.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            if (this.SE) {
                tmp = this.SE.nearest_neighbor(pt);
                if (tmp && tmp.best < min.best) {
                    min = tmp;
                }
            }

            return min;
        };

        this.receive = function (packet) {
          // This is called when somebody else sends us a packet.
          // No assumptions. Do your own link-layer authentication =)
        };
    }

    function get_neighbors_in_radius(qt, pt, radius) {
        var neighborhood = [];

        if (qt) {
            if (qt.pt.squared_distance_from(pt) < radius * radius) {
                neighborhood.push(qt);
            }

            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.NW, pt, radius));
            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.NE, pt, radius));
            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.SW, pt, radius));
            neighborhood.push.apply(neighborhood, get_neighbors_in_radius(qt.SE, pt, radius));
        }

        return neighborhood;
    }

    function plot_point(pt) {
        G.ctx.beginPath();
        G.ctx.arc(pt.x, pt.y, 3, 2 * Math.PI, false);
        G.ctx.fillStyle = pt.color;
        G.ctx.fill();
    }

    function highlight_neighbors(pt, color, radius) {
        var neighbors, i;
        neighbors = get_neighbors_in_radius(G.quadtree, pt, radius === undefined ? pt.radius : radius);
        for (i = 0; i < neighbors.length; i += 1) {
            neighbors[i].pt.color = color === undefined ? NEIGHBOR_COLOR : color;
            plot_point(neighbors[i].pt);
        }
    }

    function canvas_click(e) {
        if (G.quadtree) {
            var coords, closest_point;

            coords = G.canvas.relMouseCoords(e);
            closest_point = G.quadtree.nearest_neighbor(new Point(coords.x, coords.y));

            if (closest_point.qt === G.src) {
                highlight_neighbors(G.src.pt, NORMAL_COLOR);
                G.src = null;
                closest_point.qt.pt.color = NORMAL_COLOR;
                G.src_node.innerHTML = '(none)';
            } else if (closest_point.qt === G.dst) {
                highlight_neighbors(G.dst.pt, NORMAL_COLOR);
                G.dst = null;
                closest_point.qt.pt.color = NORMAL_COLOR;
                G.dst_node.innerHTML = '(none)';
            } else if (null === G.src) {
                G.src = closest_point.qt;
                highlight_neighbors(G.src.pt, NEIGHBOR_COLOR);
                G.src.pt.color = SOURCE_COLOR;
                G.src_node.innerHTML = G.src.toString();
            } else if (null === G.dst) {
                G.dst = closest_point.qt;
                highlight_neighbors(G.dst.pt, NEIGHBOR_COLOR);
                G.dst.pt.color = DEST_COLOR;
                G.dst_node.innerHTML = G.dst.toString();
            } else {
                G.dst.pt.color = NORMAL_COLOR;
                highlight_neighbors(G.dst.pt, NORMAL_COLOR);
                plot_point(G.dst.pt);
                G.dst = closest_point.qt;
                highlight_neighbors(G.dst.pt, NEIGHBOR_COLOR);
                G.dst_node.innerHTML = G.dst.toString();
                G.dst.pt.color = DEST_COLOR;
            }

            plot_point(closest_point.qt.pt);
        }
    }

    function create_canvas(width, height) {
        var canvas = document.createElement('canvas');
        canvas.setAttribute('id', 'map');
        canvas.setAttribute('width', width);
        canvas.setAttribute('height', height);
        canvas.addEventListener('click', function (e) { canvas_click(e); }, false);
        return canvas;
    }

    function init(x_dimension, y_dimension) {
        G = {};
        G.width = x_dimension;
        G.height = y_dimension;
        G.canvas = create_canvas(G.width, G.height);
        G.ctx = G.canvas.getContext('2d');
        document.getElementById('canvas_container').appendChild(G.canvas);
        G.quadtree = null;
        G.pixel = G.ctx.createImageData(1, 1).data;
        G.src = G.dst = null;
        G.src_node = document.getElementById('src');
        G.dst_node = document.getElementById('dst');
    }

    function draw_quadtree(qt) {
        qt.depth_first_traversal(plot_point);
    }

    function create_nodes(count) {
        var i = 0;

        if (!G.quadtree && count > 0) {
            G.quadtree = new QuadTree(randomPoint(G.width, G.height));
            i = 1;
        }

        for (i; i < count; i += 1) {
            G.quadtree.insert(randomPoint(G.width, G.height));
        }

        if (G.quadtree) {
            draw_quadtree(G.quadtree);
        }
    }

    function wagumba() {
    }

    function broadcast_to_neighbors(qt_src, packet) {
      // send to someone by calling their receive method, lol
    }

    return { 'init': init, 'create_nodes': create_nodes, 'wagumba': wagumba };
}());
<|endoftext|>