Form API ajax calls reload attached JS using behaviors I have leaflet map attached to my form, this is the container div I used:

$form['general']['map'] = array(
  '#markup' =&gt; '&lt;div class="map-wrapper" id="ngmap"&gt;&lt;/div&gt;',
);


Everything works fine and map's being loaded. I also added an image upload functionality in bottom of my form like this:

$form['detailed']['img'] = array(
  '#type' =&gt; 'managed_file',
  '#upload_location' =&gt; 'public://map-images/',
  '#required' =&gt; TRUE,
  '#title' =&gt; 'Image',
  '#default_value' =&gt; $complain['image'],

);


When I click on ajax upload button after selecting the image file, it throws an error and nothings happen:


  Uncaught Error: Map container is already initialized.


Seems like uploading file is forcing leaflet.js to reload map container. My guess is ajax is reloading and rendering the whole form all over again.

How's that possible and what's the easiest fix for this? Thank you.

Edit:
How I added initializing function, look like this attached js is being recalled everytime I click on upload image ajax button:

(function($, Drupal) {

  // Custom functions and variables can go here
  Drupal.behaviors.moduleName = {
    attach:function() {
      map = new L.Map('ngmap', {center: new L.LatLng(37.472, 57.327), zoom: 13});
      googleLayer = new L.Google('HYBRID');
      map.addLayer(googleLayer);
    }
  };
}(jQuery, Drupal));
Drupal calls every declared behaviors when an AJAX call is performed. This is done to apply the declared behaviors to new loaded content via AJAX. 

When a behavior is applied to an element a class is used to mark that element as behavior processed, so next behavior call ignore this element. The recommended way to do this is using the jQuery Once, included in Drupal 7. See the behaviors section of this page. 

In your case you should use something like this:

(function($) {

  // Custom functions and variables can go here
  Drupal.behaviors.moduleName = {
    attach:function(context, settings) {
      $('#ngmap', context).once('leaflet', function () {
        map = new L.Map('ngmap', {center: new L.LatLng(37.472, 57.327), zoom: 13});
        googleLayer = new L.Google('HYBRID');
        map.addLayer(googleLayer);
      });
    }
  };
}(jQuery));


Once will add a 'leaflet-processed' class to the #ngmap element, so next time the behavior is called the initialized map is ignored.

Imagine you have several maps in the same page, and imagine you can load more by using AJAX calls. The above code, with some modifications, allows you to initialize every new loaded map after the AJAX call.

So, your fix works but is not the right way to do it (in general inline code is discouraged), I recommend you to use the #attached and Once approach.