1

I have a javascript code that I need to repeat many times with just a slight change:

I need to take the function below and repeat it EXACTLY the same apart from changing info_throbber to video_throbber, then, to map_throbber, then picture_throbber and do tyhese changes only on 2 lines: line 2 and 9)

I don't want to just repeat theses dozens of line one after the other, even if it works. I would like to factorize it.

$(function() {
   var $modal_types  = $('select#game_info_throbber_modal_types') # FIRST INJECTION HERE 
   , $li           = $modal_types.parent('li')
   , $ol           = $li.parent('ol')
   , $form         = $modal_types.closest('form')
   , $submit       = $form.find('input[type=submit]')
   , $add_modal    = $('<a href="#">Add Modal</a>')
   , $remove_modal = $('<a href="#">Remove Modal</a>')
   , $hidden_info_modals = $('input[id=game_info_throbber][type=hidden]')  # SECOND INJECTION HERE 
  ;

  $add_modal.click(function(e) {
    e.preventDefault();

      .append($remove_modal.clone(true));
    create_info_modal($li.clone());
  });

  $remove_modal.click(function(e) {
    e.preventDefault();

    $(this).parent('li').remove();
  });


});

Using Loop through an array in JavaScript, here what I tried but it fails:

var i, s, myStringArray = [ "info_throbber", "video_throbbe", "map_throbber", "picture_throbber" ], len = myStringArray.length
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do stuff with s ...
    $(function() {
      var $modal_types  = $('select#deal_' + s + '_modal_types') 
        , $li           = $modal_types.parent('li')
        , $ol           = $li.parent('ol')
        , $form         = $modal_types.closest('form')
        , $submit       = $form.find('input[type=submit]')
        , $add_modal    = $('<a href="#">Add Modal</a>')
        , $remove_modal = $('<a href="#">Remove Modal</a>')
        , $hidden_info_modals = $('input[id=deal_' + s + '][type=hidden]')
      ;

      $add_modal.click(function(e) {
        e.preventDefault();

        $(this).closest('li')
          .append($remove_modal.clone(true));
        create_info_modal($li.clone());
      });

      $remove_modal.click(function(e) {
        e.preventDefault();

        $(this).parent('li').remove();
      });


      };   

  }
};

The problem is it seems to work but not fully as it did not append on both $add_modal nor does it allow to change values. I don't think it's necessary to understand deeply the complexe code above but the thing is it does not work while when I just put all of the 4 functions one after the other one (first for info_throbber, then video_throbber, and so on...), it works. So me creating an iteraiton through the array should be work.

thanks for yourt help,

Community
  • 1
  • 1
Mathieu
  • 4,587
  • 11
  • 57
  • 112

1 Answers1

1

You have a JavaScript scope issue. The function within the loop is only using the last i value provided for all iterations of that function. You need to pass the index into the function to make it work correctly.

See this stack question, JavaScript loop variable scope, for more information.

The simplest fix is to wrap your function like so

var i, myStringArray = [ "info_throbber", "video_throbber", "map_throbber", "picture_throbber" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  (function(index) {
    var s = myStringArray[index];
    // ... do stuff with s ...
    $(function() {
      var $modal_types  = $('select#deal_' + s + '_modal_types') 
        , $li           = $modal_types.parent('li')
        , $ol           = $li.parent('ol')
        , $form         = $modal_types.closest('form')
        , $submit       = $form.find('input[type=submit]')
        , $add_modal    = $('<a href="#">Add Modal</a>')
        , $remove_modal = $('<a href="#">Remove Modal</a>')
        , $hidden_info_modals = $('input[id=deal_' + s + '][type=hidden]')
      ;

      $add_modal.click(function(e) {
        e.preventDefault();

        $(this).closest('li')
          .append($remove_modal.clone(true));
        create_info_modal($li.clone());
      });

      $remove_modal.click(function(e) {
        e.preventDefault();

        $(this).parent('li').remove();
      });

      $submit.click(function(e) {
        var components = JSON.stringify( collect_info_modals() )
        ;

        $ol.find('ol.info_modal').remove();
        $modal_types.remove();

        $hidden_info_modals.val( components );
      });

      var modal_types_change = function() {
        var $el = $(this)
          , $li = $(this).closest('li')
          , id = $(this).val()
          , $components = $li.find('ol.components')
        ;

        $components.remove();

        get_modal_structure(id, $li.find('select') );
      };

      $modal_types.attr({ id: null, name: null });

      $li.remove();

      var create_info_modal = function($modal, modal_type_id) {

        var $select = $modal_types.clone();

        if($modal.find('select').length) { $select = $modal.find('select'); }

        $select.val(modal_type_id); 
        $select.change(modal_types_change);

        $modal.prepend($select);
        $modal.append($add_modal);

        $ol.append($modal);
      };

      var collect_info_modals = function() {
        var $info_modals = $ol.find('ol.components')
          , components   = []
        ;

        $.each($info_modals, function(_, $info_modal) {
          $info_modal    = $($info_modal);

          var info_modal = {}
            , $components  = $info_modal.find('li.component input')
            , modal_id   = $info_modal.parent('li').find('select').val()
          ;

          info_modal['modal_id'] = modal_id;

          $.each($components, function(_, component) {
            component = $(component);

            key = component.attr('name');
            val = component.val();
            info_modal[key] = val;

            component.remove();
          });

          $info_modal.parent('li').remove();
          components.push(info_modal);
        });

        return components;
      };

      function get_modal_structure(id, $select) {
        // Grab modal structure
        var url = '/admin/modal_types/modal_structure?id='+id;

        $.getJSON(url, function(modal_structure) {
          var $ol = $('<ol class="components">');

          modal_structure.forEach(function(component){
            $ol.append(build(component));
          });

          $ol.insertAfter($select);
        });
      };

      function build(component, value) {

        value = value || '';

        var text_maxlength = 300
          , $li    = $('<li class="component string input stringish" />')
          , $label = $('<label>'+component+'</label>')
          , $input = $('<input name="'+component+'" type="text" required="required" maxlength='+text_maxlength+' value="' + value + '"/>')
        ;

        // validations
        if(component.match(/^text/)) {
          $input.attr('maxlength', text_maxlength);
        }

        $li
          .append($label) // returns the LI NOT THE LABEL
          .append($input);

        return $li;
      };



      (function() {
        var hidden_info_modals = ($hidden_info_modals.val().length) ? $hidden_info_modals.val() : '[]';

        hidden_info_modals = JSON.parse( hidden_info_modals );

          hidden_info_modals.forEach(function(info_modal) {
              var modal_type_id
                , $info_modal = $li.clone(true)
                , $ol = $('<ol class="components">');
            ;

              modal_type_id = info_modal['modal_id'];

              delete info_modal['modal_id'];

              for (var key in info_modal) {
                  $ol.append(build(key, info_modal[key]));
                }

              $info_modal.append($ol)
              $info_modal.append($remove_modal.clone(true))
              create_info_modal($info_modal, modal_type_id);
          });
      })();

      create_info_modal($li.clone(true));

    });
  })(i);
}

Also, you should remove if (i in myStringArray) as that is only needed when you do a foreach loop over the attributes of an object, not when you are looping over the indexes of an array.

Community
  • 1
  • 1
Brant Olsen
  • 5,628
  • 5
  • 36
  • 53
  • did not work, it might be that I need more details on how your loop works, I mean here for example on your code above, how does i goes from 0 to 3, or loop within the array ? – Mathieu Jul 06 '15 at 19:02
  • @Mathieu Added the full function with modifications. – Brant Olsen Jul 06 '15 at 19:08
  • thanks, I'm a newbie i had applied your suggesiton only half well; will try the new one – Mathieu Jul 06 '15 at 19:12