0

I have a active_admin.js file (active admin is the name of my back office panel) that loads JavaScript for my back office pages.

I haved added custom JavaScript to one of the form (for deals) and it works perfectly.

The problem is that on other NO 'deal pages' (ex: back office pages for Users), one of the variable I specifically use inside Deal pages ($hidden_info_modals) is not present and therefore, I get a serious javascript error (notably blocking some crucial functions such as "select all").

I don't want to create a JavaScript file for each page because this file is loaded for all active amdin files inside my js assets pipeline.

What should I do?

How can I avoid this js error being generated pages where theses variables are not present (while still keeping it as it is useful on the 'edit deal' page) ?

The Error I get:

TypeError: $hidden_info_modals.val(...) is undefined

Here is active_admin.js:

The part generating the error where hidden_info_modals is not recognized on non-deal pages is at the bottom of this file:

// generating and collecting each modal types (info, improve shots...) with a loop
var i, s, myStringArray = [ "info_throbber", "improve_shots_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"  aria-required="true" 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);

};

Thanks for any help.

Mathieu
  • 4,587
  • 11
  • 57
  • 112
  • Check if the admin variable is not undefined before calling your logic for the hidden modals. – IfTrue Aug 31 '15 at 17:43
  • 1
    if (typeof variable !== 'undefined') { // the variable is defined } http://stackoverflow.com/questions/5113374/javascript-check-if-variable-exists-is-defined-initialized-which-method-is-b – IfTrue Aug 31 '15 at 17:45
  • I see, there is no other cleaner way? t does not feel very scalabable: if you must add ' if (typeof variable !== 'undefined') { // the variable is defined }' for all variables that are not PRESENT in ALL views (100s of pages maybe). you end up doing it for all variables if they are not present in every single view? – Mathieu Aug 31 '15 at 17:47
  • It's your code bro.... – Hackerman Aug 31 '15 at 17:52
  • 1
    After looking at your code perhaps in your specific case you could set $hidden_info_modals to a blank array on every page or maybe your authentication system should have some sort role based concept to it so that you can check if the person viewing the page is an admin or not, if so you display the modal. I am not going to begin the discussion of security if you are allowing admin modals to be visible just because they are in an array, that is a different discussion by itself. Are the modals different on every page? If not it seems like there is a better way to do what you are attempting. – IfTrue Aug 31 '15 at 17:54
  • @IfTrue thanks for your answer. Isn't what you just suggested exactly what I do inmy code (rookie here): I wrote var hidden_info_modals = ($hidden_info_modals.val().length) ? $hidden_info_modals.val() : '[]'; – Mathieu Aug 31 '15 at 18:00
  • Yeah but that is in your admin page so that variable wouldn't be defined in your other pages. – IfTrue Aug 31 '15 at 18:03
  • too complex for me. thanks for your inputs anyhow – Mathieu Aug 31 '15 at 18:10

0 Answers0