<commit_before># GridEditWidget is the main widget, has the form and has GridListWidget as a child.
#
# This can be used in a controller in the following way, where 'contact' is the name of
# a resource.  #grid_edit_widget is defined in grid_widget.rb.
#
#   include JqgridSupport::Controller
#   include Apotomo::Rails::ControllerMethods
# 
#   has_widgets do |root|
#     root << grid_edit_widget('contact') do |c|
#       [...configuration options...]
#     end
#   end
#
# The resource should be the name of a model, in underscore form.  It is used
# to retrieve the records for display.  A couple of further options can be
# placed after resource as parameters.  The widget_id will be resource_widget
# unless :widget_id is set explicitly.  You can pass other options, which will be
# passed on to apotomo's widget, and could, for example, be used in app-defined mixins.
#
#     root << grid_edit_widget('contact', :widget_id => 'wid', :beer => :insufficient) do |c|
#       [...configuration options...]
#     end
#
# Configuration options come in several types:
#   Grid DOM id:: Use dom_id (attribute), defaults to resource_widget (like widget_id)
#   Grid options:: Use grid_options (attribute)
#   Column options:: Use add_column
#   Query options:: Use includes (attribute)
#   Filter options:: Use add_filter_group and add_filter to create
#   Custom output methods:: Define as usual in the passed block
#   Form template name:: Use form_template (attribute),
#  looks in app/cells/grid_form_widget/form/ for {form_template}.html.erb, and
#  defaults to {controller}.
#   Where clause for sub-widgets:: Use where (attribute), define with lambda expecting parent id.
#
# They can all be set in a single configuration block and intermixed, though order
# does matter when defining columns and filters.
#
# For example:
#
#   has_widgets do |root|
#     root << grid_edit_widget('contact') do |c|
#       c.grid_options {:title => 'Contacts list'}
#       c.has_includes :categories
#       c.add_column('name', :custom => :custom_name)
#       def c.custom_name(name)
#         "[#{name}]"
#       end
#       c.add_filter_group('categories', :where => lambda {|x| {category_id => x}}) do |g|
#         Category.all.each {|cat| g.add_filter(cat.id, cat.name)}
#       end
#     end
#   end
#
# Columns can have custom output methods, defined in the configuration block.
# There are a couple of these methods already defined here that can be used.
# 
# * :custom_yn (for booleans, display 'Yes' if true otherwise 'No')
# * :custom_check (like :custom_yn, but displays a checkmark or nothing)
# * :custom_abbrev (for long strings, cuts it off at 20 characters and provides ellipses)
class GridEditWidget < Apotomo::Widget
  include GridWidget::Controller
  include AppSupport::Controller
  
  attr_accessor :includes
  attr_accessor :grid_options
  attr_accessor :dom_id
  attr_accessor :form_template
  attr_accessor :where
  attr_reader :resource
  attr_reader :columns, :sortable_columns, :default_sort
  attr_reader :filters, :filter_sequence
  attr_reader :filter_default
  
  after_initialize :setup

  # TODO: Try this later
  # responds_to_event :formSubmit, :with => :form_submitted
  
  after_add do |me, parent|
    me.respond_to_event :formSubmit, :from => me.name, :with => :form_submitted, :on => me.name
  end
  
  # Draw the empty form and list
  def display
    render
  end
  
  # catch the :recordSelected event, originates from the list.
  # send the JS to populate and reveal the form.  Uses #display_form
  def reveal_form
    # Make a new form div so we can slide away the old one and swap ids
    # (This all relies on the id of the form corresponding to an enclosing div, incidentally)
    form = @dom_id + '_form'
    clone_form = <<-JS
    $('##{form}').clone().hide().css('background-color','#DDDDFF').attr('id','new_#{form}').insertAfter('##{form}');
    $('##{form}').attr('id', 'ex_#{form}');
    $('#new_#{form}').attr('id', '#{form}');
    JS
    # slide in the new one and slide out and destroy the old one
    swap_display = <<-JS
    $('##{form}').slideDown('fast');
    $('#ex_#{form}').slideUp('fast', function() { $(this).remove();});
    JS
    # This is kind of an internal use of a state, but, you know, it works.
    render :text => clone_form + self.display_form + ';' + swap_display
  end
  
  def display_form
    @record = fetch_record
    # TODO: Is parentSelection redundant?  Can't I just watch for :recordSelected?
    # trigger :parentSelection, :pid => @record.id
    # TODO: Try to pass fewer locals
    update :selector => @dom_id + '_form', :view => 'form/' + @form_template, :layout => 'form_wrapper', :locals =>
      {:container => @dom_id + '_form', :resource => @resource, :record => @record}
  end

  # TODO: Make this work.<commit_msg>Embedding now works in the abstract, but the embedded widget doesn't respond to the parent's id.<commit_after># GridEditWidget is the main widget, has the form and has GridListWidget as a child.
#
# This can be used in a controller in the following way, where 'contact' is the name of
# a resource.  #grid_edit_widget is defined in grid_widget.rb.
#
#   include JqgridSupport::Controller
#   include Apotomo::Rails::ControllerMethods
# 
#   has_widgets do |root|
#     root << grid_edit_widget('contact') do |c|
#       [...configuration options...]
#     end
#   end
#
# The resource should be the name of a model, in underscore form.  It is used
# to retrieve the records for display.  A couple of further options can be
# placed after resource as parameters.  The widget_id will be resource_widget
# unless :widget_id is set explicitly.  You can pass other options, which will be
# passed on to apotomo's widget, and could, for example, be used in app-defined mixins.
#
#     root << grid_edit_widget('contact', :widget_id => 'wid', :beer => :insufficient) do |c|
#       [...configuration options...]
#     end
#
# Configuration options come in several types:
#   Grid DOM id:: Use dom_id (attribute), defaults to resource_widget (like widget_id)
#   Grid options:: Use grid_options (attribute)
#   Column options:: Use add_column
#   Query options:: Use includes (attribute)
#   Filter options:: Use add_filter_group and add_filter to create
#   Custom output methods:: Define as usual in the passed block
#   Form template name:: Use form_template (attribute),
#  looks in app/cells/grid_form_widget/form/ for {form_template}.html.erb, and
#  defaults to {controller}.
#   Where clause for sub-widgets:: Use where (attribute), define with lambda expecting parent id.
#
# They can all be set in a single configuration block and intermixed, though order
# does matter when defining columns and filters.
#
# For example:
#
#   has_widgets do |root|
#     root << grid_edit_widget('contact') do |c|
#       c.grid_options {:title => 'Contacts list'}
#       c.has_includes :categories
#       c.add_column('name', :custom => :custom_name)
#       def c.custom_name(name)
#         "[#{name}]"
#       end
#       c.add_filter_group('categories', :where => lambda {|x| {category_id => x}}) do |g|
#         Category.all.each {|cat| g.add_filter(cat.id, cat.name)}
#       end
#     end
#   end
#
# Columns can have custom output methods, defined in the configuration block.
# There are a couple of these methods already defined here that can be used.
# 
# * :custom_yn (for booleans, display 'Yes' if true otherwise 'No')
# * :custom_check (like :custom_yn, but displays a checkmark or nothing)
# * :custom_abbrev (for long strings, cuts it off at 20 characters and provides ellipses)
class GridEditWidget < Apotomo::Widget
  include GridWidget::Controller
  include AppSupport::Controller
  
  attr_accessor :includes
  attr_accessor :grid_options
  attr_accessor :dom_id
  attr_accessor :form_template
  attr_accessor :where
  attr_reader :resource
  attr_reader :columns, :sortable_columns, :default_sort
  attr_reader :filters, :filter_sequence
  attr_reader :filter_default
  
  after_initialize :setup

  # TODO: Try this later
  # responds_to_event :formSubmit, :with => :form_submitted
  
  after_add do |me, parent|
    me.respond_to_event :formSubmit, :from => me.name, :with => :form_submitted, :on => me.name
  end
  
  # Draw the empty form and list
  def display
    render
  end
  
  # catch the :recordSelected event, originates from the list.
  # send the JS to populate and reveal the form.  Uses #display_form
  def reveal_form
    # Make a new form div so we can slide away the old one and swap ids
    # (This all relies on the id of the form corresponding to an enclosing div, incidentally)
    # Forcibly remove any jqgrids still there or there will be a problem loading the new one
    form = @dom_id + '_form'
    clone_form = <<-JS
    $('##{form}').clone().hide().css('background-color','#DDDDFF').attr('id','new_#{form}').insertAfter('##{form}');
    $('##{form}').attr('id', 'ex_#{form}');
    $('#ex_#{form} .ui-jqgrid').remove();
    $('#new_#{form}').attr('id', '#{form}');
    JS
    # slide in the new one and slide out and destroy the old one
    swap_display = <<-JS
    $('##{form}').slideDown('fast');
    $('#ex_#{form}').slideUp('fast', function() { $(this).remove();});
    JS
    # This is kind of an internal use of a state, but, you know, it works.
    render :text => clone_form + self.display_form + ';' + swap_display
  end
  
  def display_form
    @record = fetch_record
    # TODO: Is parentSelection redundant?  Can't I just watch for :recordSelected?
    # trigger :parentSelection, :pid => @record.id
    # TODO: Try to pass fewer locals
    update :selector => @dom_id + '_form', :view => 'form/' + @form_template, :layout => 'form_wrapper', :locals =>
      {:container => @dom_id + '_form', :resource => @resource, :record => @record}
  end

  # TODO: Make this work.
{'fraction_non_alphanumeric': 0.11800610376398779, 'fraction_numerical': 0.0004069175991861648, 'mean_word_length': 3.760774818401937, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 41, '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': '5810764', 'n_tokens_mistral': 3009, 'n_tokens_neox': 2983, 'n_words': 1096}