<commit_before>module ChainSelectsHelper
  # creates a chain of drop-down boxes given a set of models
  def chain_select_ajax(options = {})
    html = ""
    
    prefix = (options[:prefix] or 'chain_select').to_s
    spacer = (options[:spacer] or '').to_s
    
    if options[:models]
      for model_name in options[:models]

        # get options for this model
        options = chain_select_model_options(model_name, options)
        
        # don't add the spacer on the last drop-down
        spacer = '' if options[:models].last == model_name
        
        html += (chain_select_for_model(model_name, prefix, options) + spacer)
      end
    end
    
    unless options[:disable_ajax_indicator]
      html += chain_select_indicator('global', prefix)
    end
    
    html
  end
  
  def chain_select_stand_alone(model_name, options = {})
    ar_model = constantize_model(model_name)
    prefix = (options[:prefix] or 'chain_select').to_s

    # adapt the :value to look like it is being called
    # from chain_select_ajax(:values => {:manufacturer => 2, :brand => 4, :make_model => 3})
    if options[:value] and options[:parent]
      options[:values] = {}
      options[:values][model_name] = options[:value]
      options[:values][ar_model.chain_select_from] = options[:parent]
    end

    # get options for this model
    options = chain_select_model_options(model_name, options)
    
    chain_select_for_model(model_name, prefix, options)
  end
  
  # sets up the options for the model
  def chain_select_model_options(model_name, options = {})
    ar_model = constantize_model(model_name)
    
    # always display the data for the 1st drop-down
    if ar_model.is_chain_select_root?
      options[:select_txt_only] = nil
      options[:value] = options[:values][model_name] if options[:values] and options[:values][model_name]
      
    # for succeeding drop-downs, either display a plain "-- Select --"
    # or display a selected value
    else
      # user specified a value so we need to retrieve all data that are related to it
      if options[:values] and options[:values][model_name]
        options[:value] = options[:values][model_name]
        options[:parent] = [options[:values][ar_model.chain_select_from], ar_model.chain_select_from.to_s]
      else
        options[:select_txt_only] = true
      end
    end
    
    options
  end
  
  def chain_select_indicator_stand_alone(prefix)
    chain_select_indicator('global', prefix)
  end
  
  def chain_select_for_model(model_name, prefix = 'chain_select', options = {})
    # make the model callable (summoning ...)
    ar_model = constantize_model(model_name)
    
    # element id of the drop-down
    select_name = chain_select_name(model_name, prefix)
    
    drop_down_options = {}
    drop_down_options[:class_name] = model_name.to_s
    drop_down_options[:select_txt_only] = true if options[:select_txt_only]
    drop_down_options[:disable_select_txt] = true if options[:disable_select_txt]
    drop_down_options[:parent] = options[:parent] if options[:parent]
    
    # get the data for the drop-down
    select_option_data = ar_model.chain_drop_down(drop_down_options)
    
    # generate the options and more importantly, the code for ajax events
    select_options = chain_select_options(model_name, prefix)
    select_options[:value] ||= options[:value]
    
    # model is not a chain for anything, i.e. last drop-down
    unless ar_model.can_chain_child?
      select_options[:onchange] = nil
    end
    
    select_options[:name] = chain_select_form_name(model_name, prefix)
    
    select_options_tag(select_name, select_option_data, select_options)
  end
  
  # generates the spinning ajax indicator
  # this is not configurable at the moment
  # just replace the file ajax-loader in public/images
  # if you want to change it
  def chain_select_indicator(model_name, prefix = 'chain_select')
    image_tag('ajax-loader.gif', :id => chain_select_indicator_name(model_name, prefix), :style => 'display: none;', :class => 'chain_select_indicator')
  end
  
  # creates a vanila drop-down select box
  # name - name of the select box
  # select_options - an array that contains the contents of the drop-down
  #                  select box, each element of the 
  #                  array contains a sub-array in the format of:
  #                  ['Text', id]
  #                  Where 'Text' appears in the drop-down box
  # options - misc html options
  def select_options_tag(name = '', select_options = {}, options= {})
    selected = ''
    
    unless options[:value].blank?
      selected = options[:value]
      options.delete(:value)
    end
    <commit_msg>Ability to run JS code after last chain select.<commit_after>module ChainSelectsHelper
  # creates a chain of drop-down boxes given a set of models
  def chain_select_ajax(options = {})
    html = ""
    
    prefix = (options[:prefix] or 'chain_select').to_s
    spacer = (options[:spacer] or '').to_s
    
    if options[:models]
      for model_name in options[:models]

        # get options for this model
        options = chain_select_model_options(model_name, options)
        
        # don't add the spacer on the last drop-down
        spacer = '' if options[:models].last == model_name
        
        # user specified something to do for the last drop-down's onchange event
        if block_given?
          ar_model = constantize_model(model_name)
          unless ar_model.can_chain_child?
            options[:onchange] = render(:update) { |page| yield(page) }
          end
        end
        
        html += (chain_select_for_model(model_name, prefix, options) + spacer)
      end
    end
    
    unless options[:disable_ajax_indicator]
      html += chain_select_indicator('global', prefix)
    end
    
    html
  end
  
  def chain_select_stand_alone(model_name, options = {})
    ar_model = constantize_model(model_name)
    prefix = (options[:prefix] or 'chain_select').to_s

    # adapt the :value to look like it is being called
    # from chain_select_ajax(:values => {:manufacturer => 2, :brand => 4, :make_model => 3})
    if options[:value] and options[:parent]
      options[:values] = {}
      options[:values][model_name] = options[:value]
      options[:values][ar_model.chain_select_from] = options[:parent]
    end

    # get options for this model
    options = chain_select_model_options(model_name, options)
    
    chain_select_for_model(model_name, prefix, options)
  end
  
  # sets up the options for the model
  def chain_select_model_options(model_name, options = {})
    ar_model = constantize_model(model_name)
    
    # always display the data for the 1st drop-down
    if ar_model.is_chain_select_root?
      options[:select_txt_only] = nil
      options[:value] = options[:values][model_name] if options[:values] and options[:values][model_name]
      
    # for succeeding drop-downs, either display a plain "-- Select --"
    # or display a selected value
    else
      # user specified a value so we need to retrieve all data that are related to it
      if options[:values] and options[:values][model_name]
        options[:value] = options[:values][model_name]
        options[:parent] = [options[:values][ar_model.chain_select_from], ar_model.chain_select_from.to_s]
      else
        options[:select_txt_only] = true
      end
    end
    
    options
  end
  
  def chain_select_indicator_stand_alone(prefix)
    chain_select_indicator('global', prefix)
  end
  
  def chain_select_for_model(model_name, prefix = 'chain_select', options = {})
    # make the model callable (summoning ...)
    ar_model = constantize_model(model_name)
    
    # element id of the drop-down
    select_name = chain_select_name(model_name, prefix)
    
    drop_down_options = {}
    drop_down_options[:class_name] = model_name.to_s
    drop_down_options[:select_txt_only] = true if options[:select_txt_only]
    drop_down_options[:disable_select_txt] = true if options[:disable_select_txt]
    drop_down_options[:parent] = options[:parent] if options[:parent]
    
    # get the data for the drop-down
    select_option_data = ar_model.chain_drop_down(drop_down_options)
    
    # generate the options and more importantly, the code for ajax events
    select_options = chain_select_options(model_name, prefix)
    select_options[:value] ||= options[:value]
    
    # model is not a chain for anything, i.e. last drop-down
    unless ar_model.can_chain_child?
      select_options[:onchange] = nil
      
      if options[:onchange]
        select_options[:onchange] = options[:onchange]
      end
    end
    
    select_options[:name] = chain_select_form_name(model_name, prefix)
    
    select_options_tag(select_name, select_option_data, select_options)
  end
  
  # generates the spinning ajax indicator
  # this is not configurable at the moment
  # just replace the file ajax-loader in public/images
  # if you want to change it
  def chain_select_indicator(model_name, prefix = 'chain_select')
    image_tag('ajax-loader.gif', :id => chain_select_indicator_name(model_name, prefix), :style => 'display: none;', :class => 'chain_select_indicator')
  end
  
  # creates a vanila drop-down select box
  # name - name of the select box
  # select_options - an array that contains the contents of the drop-down
  #                  select box, each element of the 
  #                  array contains a sub-array in the format of:
  #                  ['Text', id]
  #                  Where 'Text' appears in the drop-down box
  # options - misc html options
  def select_options_tag(name = '', select_options = {}, options= {})
    selected = ''
    
    unless options[:value].blank?
      selected = options[:value]
      options.delete(:value)
    end
    
{'fraction_non_alphanumeric': 0.09184715978749489, 'fraction_numerical': 0.0008173273395995096, 'mean_word_length': 3.1338682432432434, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4997644', 'n_tokens_mistral': 2932, 'n_tokens_neox': 2893, 'n_words': 786}