#= require spin spinner_opts = lines: 8 length: 4 width: 3 radius: 5 $ -> if $('.polymorphic_has_many_container').length form = $('#main_content').find('form:first') $(form).on 'submit', (e) -> submissions_counter = 0 parentForm = @ expect = $(@).find('form').length if submissions_counter < expect e.preventDefault() $(@).find('form').each -> remoteSubmit @, -> submissions_counter++ if submissions_counter == expect $(form).find('form').remove() stripEmptyRelations() $(parentForm).submit() $(document).on "upload:start", "form", (event) -> form = $('#main_content').find('form:first') form.find("input[type=submit]").attr "disabled", true $(document).on "upload:complete", "form", (event) -> form = $('#main_content').find('form:first') unless form.find("input.uploading").length form.find("input[type=submit]").removeAttr "disabled" $('.polymorphic_has_many_fields').each (index, rapper) -> rapper = $ rapper hiddenField = rapper.find 'input[type=hidden][data-path]' formPath = hiddenField.data 'path' extractAndInsertForm formPath, rapper $(document).on 'click', 'a.button.polymorphic_has_many_remove', (e) -> e.preventDefault() parent = $(@).closest '.polymorphic_has_many_container' to_remove = $(@).closest 'fieldset' recompute_positions parent parent.trigger 'polymorphic_has_many_remove:before', [to_remove, parent] to_remove.remove() parent.trigger 'polymorphic_has_many_remove:after', [to_remove, parent] $(document).on 'click', 'a.button.polymorphic_has_many_add', (e) -> e.preventDefault() parent = $(@).closest '.polymorphic_has_many_container' parent.trigger before_add = $.Event('polymorphic_has_many_add:before'), [parent] unless before_add.isDefaultPrevented() index = parent.data('polymorphic_has_many_index') || parent.children('fieldset').length - 1 parent.data has_many_index: ++index regex = new RegExp $(@).data('placeholder'), 'g' html = $(@).data('html').replace regex, index fieldset = $(html).insertBefore(@) recompute_positions parent parent.trigger 'polymorphic_has_many_add:after', [fieldset, parent] init_polymorphic_sortable() $('.polymorphic_has_many_container').on 'change', '.polymorphic_type_select', (event) -> fieldset = $(this).closest 'fieldset' selectedOption = $(this).find 'option:selected' formPath = selectedOption.data 'path' label = $(this).prev 'label' label.remove() hiddenField = $('') hiddenField.attr 'name', $(this).attr('name') hiddenField.val $(this).val() $(this).replaceWith hiddenField newListItem = $ '
  • ' extractAndInsertForm formPath, fieldset init_polymorphic_sortable = -> elems = $('.polymorphic_has_many_container[data-sortable]:not(.ui-sortable)') elems.sortable axis: 'y' items: '> fieldset', handle: '> ol > .handle', stop: recompute_positions elems.each recompute_positions # Removes relations if id or type is not specified # For example when user clicked add relation button, but didn't selected type stripEmptyRelations = -> $('.polymorphic_has_many_fields input:hidden').each -> if $(@).val() == "" $(@).parents('.polymorphic_has_many_fields').remove() recompute_positions = (parent) -> parent = if parent instanceof jQuery then parent else $(@) input_name = parent.data 'sortable' position = parseInt(parent.data('sortable-start') || 0, 10) parent.children('fieldset').each -> # We ignore nested inputs, so when defining your has_many, be sure to keep # your sortable input at the root of the has_many block. destroy_input = $(@).find "> ol > .input > :input[name$='[_destroy]']" sortable_input = $(@).find "> ol > .input > :input[name$='[#{input_name}]']" if sortable_input.length sortable_input.val if destroy_input.is ':checked' then '' else position++ init_loading_indicator = (target) -> spinner = new Spinner(spinner_opts).spin() $(target).height(50).children().hide() $(target).append spinner.el spinner stop_loading_indicator = (target, spinner) -> spinner.stop() $(target).height('').children().show() window.extractAndInsertForm = (url, target) -> target = $ target spinner = init_loading_indicator(target) container = $(target).closest '.polymorphic_has_many_container' container.trigger "polymorphic_has_many_form:beforeInsert", [ target ] $.ajax url, headers: Accept: 'text/html' success: (data) -> elements = $(data) form = $('#main_content form', elements).first() $(form).find('.actions').remove() $(form).on 'submit', -> return false stop_loading_indicator(target, spinner) target.prepend form container.trigger "polymorphic_has_many_form:inserted", [form] error: (xhr, status, error) -> stop_loading_indicator(target, spinner) window.loadErrors = (target) -> $(target).off('ajax:success').off('ajax:beforeSend') $(target).on 'ajax:beforeSend', (event, xhr, setting) -> xhr.setRequestHeader 'Accept', 'text/html' .trigger('submit.rails').on 'ajax:success', (event, data, result) -> # duplicates method above. refactor using callbacks elements = $(data) form = $('#main_content form', elements).first() $(form).find('.actions').remove() $(form).on 'submit', -> return false $(target).replaceWith(form) container = $(form).closest '.polymorphic_has_many_container' container.trigger "polymorphic_has_many_form:inserted", [ form ] window.remoteSubmit = (target, callback) -> action = $(target).attr('action') $(target).data('remote', true) $(target).removeAttr('novalidate') $(target).find("input[type=file]").remove() # unbind callbacks action for form if it was submitted before $(target).off('ajax:success').off('ajax:aborted:file').off('ajax:error').off 'ajax:beforeSend' $(target).on 'ajax:beforeSend', (event, xhr, setting) -> xhr.setRequestHeader 'Accept', 'application/json' .trigger('submit.rails') .on 'ajax:aborted:file', (inputs) -> false .on 'ajax:error', (event, response, status) -> if response.status == 422 loadErrors(target) .on 'ajax:success', (event, object, status, response) -> unless $(target).next().find('input:first').val() # create $(target).next().find('input:first').val(object.id) # replace new form with edit form # to update form method to PATCH and form action url = "#{action}/#{object.id}/edit" extractAndInsertForm(url, $(target).parent('fieldset')) $(target).remove() callback()