sanger/sequencescape

View on GitHub
app/views/shared/metadata/_related_fields.html.erb

Summary

Maintainability
Test Coverage

<%= legacy_javascript_tag do %>
  jQuery(function() {
    (function(undefined) {
      var hideSectionAndDisableInputs = function(elements) {
        // disable inputs when hidden so they don't fire validation
        elements.each(function() {
          jQuery(this).hide().find('input').attr('disabled','disabled');
        });
      };

      var showSectionAndEnableInputsIfVisible = function(elements) {
        elements.each(function() {
          jQuery(this).show();

          jQuery(this).find('input').each(function() {
            // only enable input if it's not hidden - could be beneath a hidden element in the DOM
            if(!jQuery(this).is(':visible')) return;
            jQuery(this).attr('disabled', null);
          });
        });
      };

      var valueFrom = function(element) {
        if (element === null) { return null }
        var value = element.value.toLowerCase().replace(/[^a-z0-9]+/, '_');
        return (value.length == 0) ? 'blank' : value;
      };

      var selectRelatedByFieldAndValue = function(fieldName, value) {
        return jQuery('.related_to.' + fieldName + '.' + value);
      };

      var getElementByFieldName = function(fieldName) {
        return  document.getElementById('<%= root %>_' + fieldName) ||
                jQuery("input[name='study[study_metadata_attributes]["+fieldName+"]']:checked")[0] ||
                document.getElementById('<%= root %>_' + fieldName + '_id');
      };

      rerenderFieldsRelatedToControllingField = function(fieldName, controllingField) {
        var relatedToDivs = jQuery('.related_to.' + fieldName);
        hideSectionAndDisableInputs(relatedToDivs);

        var relatedWithRelevantValue = selectRelatedByFieldAndValue(fieldName, valueFrom(controllingField));
        showSectionAndEnableInputsIfVisible(relatedWithRelevantValue);
      };

      addOnChangeHandler = function(fieldName) {
        controllingFieldSelector = '[id=<%= root %>_' + fieldName + '],[id=<%= root %>_' + fieldName + '_id],[name=\'study[study_metadata_attributes]['+fieldName+']\']';

        jQuery('body').delegate(controllingFieldSelector, 'change', function() {
          controllingField = this;
          rerenderFieldsRelatedToControllingField(fieldName, controllingField);
        });
      }

      initialize = function() {
        <% related.each do |field| %>
          var fieldName = "<%= field.to_s %>";
          var controllingField = getElementByFieldName(fieldName);

          rerenderFieldsRelatedToControllingField(fieldName, controllingField);
          addOnChangeHandler(fieldName);
        <% end %>
      }

      initialize();
    })();
  });

  (function($, undefined) {
    <% changing_fields.reverse.each do |field, options| %>
      attach_option_updater("<%= field.to_s %>", "<%= options[:when].to_s %>", {<%= options[:values].map { |k,v| "#{k.inspect}:#{v.inspect}" }.join(',').html_safe %>});
    <% end %>

    function attach_option_updater(target, source, values) {
      // selector uses 'start with id' rather than 'equals id' to include radio buttons, where ids have the value appended
      var selector = '[id^=' + '<%= root %>_' + source + ']';
      var sourceFields = $(selector);
      var isRadioButton = sourceFields.attr('type') == 'radio';

      sourceFields.change(function() {
        select_to_change_options_in = $('#<%= root %>_' + target);
        selected_option = select_to_change_options_in.val();
        options = values[this.value].map(function(value) { return '<option value="' + value + '">' + value + '</option>'; });
        select_to_change_options_in.html(options.join('')).val(selected_option);
        select_to_change_options_in.trigger('change');
      });

      // trigger change on load (for radio buttons, only if it's selected)
      sourceFields.each(function() {
        var isSelected = $(this).attr('checked') == 'checked';

        if(!isRadioButton || (isRadioButton && isSelected)) {
          $(this).trigger('change');
        }
      });
    };
  })(jQuery);
<% end %>