Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 071c48663afff3c0c3097ae9093581f55ed9d244 Nico committed May 20, 2012
@@ -0,0 +1,17 @@
+*.gem
+*.rbc
+.bundle
+.config
+.yardoc
+Gemfile.lock
+InstalledFiles
+_yardoc
+coverage
+doc/
+lib/bundler/man
+pkg
+rdoc
+spec/reports
+test/tmp
+test/version_tmp
+tmp
@@ -0,0 +1 @@
+nested_form_fields
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Settings><!--This file was automatically generated by Ruby plugin.
+You are allowed to:
+1. Remove rake task
+2. Add existing rake tasks
+To add existing rake tasks automatically delete this file and reload the project.
+--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build nested_form_fields-0.0.1.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Build and install nested_form_fields-0.0.1.gem into system gems" fullCmd="install" taksId="install" /><RakeTask description="Create tag v0.0.1 and build and push nested_form_fields-0.0.1.gem to Rubygems" fullCmd="release" taksId="release" /></RakeGroup></Settings>
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
+</project>
+
@@ -0,0 +1,11 @@
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0" is_locked="false">
+ <option name="myName" value="Project Default" />
+ <option name="myLocal" value="false" />
+ <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
+ <option name="processCode" value="true" />
+ <option name="processLiterals" value="true" />
+ <option name="processComments" value="true" />
+ </inspection_tool>
+ </profile>
+</component>
@@ -0,0 +1,7 @@
+<component name="InspectionProjectProfileManager">
+ <settings>
+ <option name="PROJECT_PROFILE" value="Project Default" />
+ <option name="USE_PROJECT_PROFILE" value="true" />
+ <version value="1.0" />
+ </settings>
+</component>
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectResources">
+ <default-html-doctype>$APPLICATION_HOME_DIR$/lib/rubymine.jar!/resources/html5-schema/html5.rnc</default-html-doctype>
+ </component>
+ <component name="ProjectRootManager" version="2" project-jdk-name="RVM: ruby-1.9.2-p290-railsexpress" project-jdk-type="RUBY_SDK" />
+</project>
+
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/nested_form_fields.iml" filepath="$PROJECT_DIR$/.idea/nested_form_fields.iml" />
+ </modules>
+ </component>
+</project>
+
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="RUBY_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v1.1.3, RVM: ruby-1.9.2-p290-railsexpress) [gem]" level="application" />
+ </component>
+</module>
+
@@ -0,0 +1,5 @@
+<component name="DependencyValidationManager">
+ <state>
+ <option name="SKIP_IMPORT_STATEMENTS" value="false" />
+ </state>
+</component>
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
+ </component>
+</project>
+
Oops, something went wrong.
@@ -0,0 +1,4 @@
+source 'https://rubygems.org'
+
+# Specify your gem's dependencies in nested_form_fields.gemspec
+gemspec
@@ -0,0 +1,22 @@
+Copyright (c) 2012 Nico Ritsche
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
+# NestedFormFields
+
+TODO: Write a gem description
+
+## Installation
+
+Add this line to your application's Gemfile:
+
+ gem 'nested_form_fields'
+
+And then execute:
+
+ $ bundle
+
+Or install it yourself as:
+
+ $ gem install nested_form_fields
+
+## Usage
+
+TODO: Write usage instructions here
+
+## Contributing
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Commit your changes (`git commit -am 'Added some feature'`)
+4. Push to the branch (`git push origin my-new-feature`)
+5. Create new Pull Request
@@ -0,0 +1,2 @@
+#!/usr/bin/env rake
+require "bundler/gem_tasks"
@@ -0,0 +1,109 @@
+require "nested_form_fields/version"
+
+module NestedFormFields
+ module Rails
+ class Engine < ::Rails::Engine
+ end
+ end
+end
+
+module ActionView::Helpers
+
+ class FormBuilder
+
+ def nested_fields_for(record_name, record_object = nil, fields_options = {}, &block)
+ fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
+ fields_options[:builder] ||= options[:builder]
+ fields_options[:parent_builder] = self
+ fields_options[:namespace] = fields_options[:parent_builder].options[:namespace]
+
+ return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
+ end
+
+
+ def add_nested_fields_link association, text = nil
+ @template.link_to text || "Add #{association.to_s.singularize.humanize}", '',
+ class: "add_nested_fields_link",
+ data: { association_path: association_path(association.to_s) }
+ end
+
+ def remove_nested_fields_link text = nil
+ @template.link_to text || 'x', '',
+ class: "remove_nested_fields_link",
+ data: { delete_association_field_name: delete_association_field_name }
+ end
+
+
+ private
+
+ def fields_for_with_nested_attributes(association_name, association, options, block)
+ name = "#{object_name}[#{association_name}_attributes]"
+ association = convert_to_model(association)
+
+ if association.respond_to?(:persisted?)
+ association = [association] if @object.send(association_name).is_a?(Array)
+ elsif !association.respond_to?(:to_ary)
+ association = @object.send(association_name)
+ end
+
+ if association.respond_to?(:to_ary)
+ explicit_child_index = options[:child_index]
+ output = ActiveSupport::SafeBuffer.new
+ association.each do |child|
+ output << nested_fields_wrapper(association_name) do
+ fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, options, block)
+ end
+ end
+
+ templates = nested_model_template(name, association_name, options, block)
+ output << templates
+
+ output
+ elsif association
+ fields_for_nested_model(name, association, options, block)
+ end
+ end
+
+
+ def nested_model_template name, association_name, options, block
+ for_template = self.options[:for_template]
+ @template.content_tag( for_template ? :div : :script,
+ type: for_template ? nil : 'text/html',
+ id: template_id(association_name),
+ class: for_template ? 'form_template' : nil,
+ style: for_template ? 'display:none' : nil ) do
+ nested_fields_wrapper(association_name) do
+ fields_for_nested_model("#{name}[#{index_placeholder(association_name)}]",
+ association_name.to_s.classify.constantize.new,
+ options.merge(for_template: true), block)
+ end
+ end
+ end
+
+
+ def template_id association_name
+ "#{association_path(association_name)}_template"
+ end
+
+ def association_path association_name
+ "#{object_name.gsub('][','_').gsub(/_attributes/,'').sub('[','_').sub(']','')}_#{association_name}"
+ end
+
+ def index_placeholder association_name
+ "__#{association_path(association_name)}_index__"
+ end
+
+ def delete_association_field_name
+ "#{object_name}[_destroy]"
+ end
+
+
+ def nested_fields_wrapper association_name
+ @template.content_tag :div, class: "nested_fields nested_#{association_path(association_name)}" do
+ yield
+ end
+ end
+
+ end
+
+end
@@ -0,0 +1,3 @@
+module NestedFormFields
+ VERSION = "0.0.1"
+end
@@ -0,0 +1,17 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('../lib/nested_form_fields/version', __FILE__)
+
+Gem::Specification.new do |gem|
+ gem.authors = ["Nico Ritsche"]
+ gem.email = ["ncrdevmail@gmail.com"]
+ gem.description = %q{Allows to dynamically add and remove nested has_many association fields in a form.}
+ gem.summary = %q{Allows to dynamically add and remove nested has_many association fields in a form.}
+ gem.homepage = ""
+
+ gem.files = `git ls-files`.split($\)
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
+ gem.name = "nested_form_fields"
+ gem.require_paths = ["lib"]
+ gem.version = NestedFormFields::VERSION
+end
@@ -0,0 +1,31 @@
+jQuery ->
+
+ $('body').on 'click', '.add_nested_fields_link', ->
+ $link = $(this)
+ association_path = $link.data('association-path')
+ $template = $("##{association_path}_template")
+
+ template_html = $template.html()
+
+ # insert association indexes
+ index_placeholder = "__#{association_path}_index__"
+ template_html = template_html.replace(new RegExp(index_placeholder,"g"), $(".nested_#{association_path}").length)
+
+ # replace child template div tags with script tags to avoid form submission of templates
+ $parsed_template = $(template_html)
+ $child_templates = $parsed_template.children('.form_template')
+ $child_templates.each () ->
+ $child = $(this)
+ $child.replaceWith($("<script id='#{$child.attr('id')}' type='text/html' />").html($child.html()))
+
+ $link.before( $parsed_template )
+ false
+
+
+ $('body').on 'click', '.remove_nested_fields_link', ->
+ $link = $(this)
+ delete_association_field_name = $link.data('delete-association-field-name')
+ $nested_fields_container = $link.parents(".nested_fields").first()
+ $nested_fields_container.before "<input type='hidden' name='#{delete_association_field_name}' value='1' />"
+ $nested_fields_container.hide()
+ false

0 comments on commit 071c486

Please sign in to comment.