From 9a46c3a1d7f4f42778567924ce74c3f130cf0ce4 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Tue, 20 Sep 2011 13:00:50 -0500 Subject: [PATCH 01/78] Generate haml templates instead erb templates --- .gitignore | 2 + .rvmrc | 48 +------------------ .../backbone/scaffold/scaffold_generator.rb | 20 ++++---- .../scaffold/templates/templates/edit.haml | 14 ++++++ .../scaffold/templates/templates/edit.jst | 17 ------- .../scaffold/templates/templates/index.haml | 17 +++++++ .../scaffold/templates/templates/index.jst | 16 ------- .../scaffold/templates/templates/model.haml | 7 +++ .../scaffold/templates/templates/model.jst | 7 --- .../scaffold/templates/templates/new.haml | 14 ++++++ .../scaffold/templates/templates/new.jst | 17 ------- .../templates/{show.jst => show.haml} | 8 ++-- 12 files changed, 68 insertions(+), 119 deletions(-) create mode 100644 lib/generators/backbone/scaffold/templates/templates/edit.haml delete mode 100644 lib/generators/backbone/scaffold/templates/templates/edit.jst create mode 100644 lib/generators/backbone/scaffold/templates/templates/index.haml delete mode 100644 lib/generators/backbone/scaffold/templates/templates/index.jst create mode 100644 lib/generators/backbone/scaffold/templates/templates/model.haml delete mode 100644 lib/generators/backbone/scaffold/templates/templates/model.jst create mode 100644 lib/generators/backbone/scaffold/templates/templates/new.haml delete mode 100644 lib/generators/backbone/scaffold/templates/templates/new.jst rename lib/generators/backbone/scaffold/templates/templates/{show.jst => show.haml} (52%) diff --git a/.gitignore b/.gitignore index e508f25..57c7c04 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ test/dummy/tmp/ test/dummy/.sass-cache/ test/tmp/**/* .idea/ +.rvmrc + diff --git a/.rvmrc b/.rvmrc index f93238c..6e30686 100644 --- a/.rvmrc +++ b/.rvmrc @@ -1,47 +1 @@ -#!/usr/bin/env bash - -# This is an RVM Project .rvmrc file, used to automatically load the ruby -# development environment upon cd'ing into the directory - -# First we specify our desired [@], the @gemset name is optional. -environment_id="ruby-1.9.2-p180@backbone-rails" - -# -# First we attempt to load the desired environment directly from the environment -# file, this is very fast and efficicent compared to running through the entire -# CLI and selector. If you want feedback on which environment was used then -# insert the word 'use' after --create as this triggers verbose mode. -# -if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \ - && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] ; then - \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id" -else - # If the environment file has not yet been created, use the RVM CLI to select. - rvm --create "$environment_id" -fi - -# -# If you use an RVM gemset file to install a list of gems (*.gems), you can have -# it be automatically loaded, uncomment the following and adjust the filename if -# necessary. -# -# filename=".gems" -# if [[ -s "$filename" ]] ; then -# rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d' -# fi - -# -# If you use bundler and would like to run bundle each time you enter the -# directory you can uncomment the following code. -# -# Ensure that Bundler is installed, install it if it is not. -if ! command -v bundle ; then - printf "The rubygem 'bundler' is not installed, installing it now.\n" - gem install bundler -fi -# -# # Bundle while redcing excess noise. -# printf "Bundling your gems this may take a few minutes on a fresh clone.\n" -# bundle | grep -v 'Using' | grep -v 'complete' | sed '/^$/d' -# - +rvm use 1.9.2@backbone-rails diff --git a/lib/generators/backbone/scaffold/scaffold_generator.rb b/lib/generators/backbone/scaffold/scaffold_generator.rb index 4ea2adc..3449895 100644 --- a/lib/generators/backbone/scaffold/scaffold_generator.rb +++ b/lib/generators/backbone/scaffold/scaffold_generator.rb @@ -3,29 +3,29 @@ module Backbone module Generators class ScaffoldGenerator < ModelGenerator - + source_root File.expand_path("../templates", __FILE__) desc "This generator creates the client side crud scaffolding" - - def create_router_files + + def create_router_files template 'router.coffee', File.join(backbone_path, "routers", class_path, "#{plural_name}_router.js.coffee") end - + def create_view_files available_views.each do |view| template "views/#{view}_view.coffee", File.join(backbone_path, "views", plural_name, "#{view}_view.js.coffee") - template "templates/#{view}.jst", File.join(backbone_path, "templates", plural_name, "#{view}.jst.ejs") + template "templates/#{view}.haml", File.join(backbone_path, "templates", plural_name, "#{view}.jst.ejs.haml") end - + template "views/model_view.coffee", File.join(backbone_path, "views", plural_name, "#{singular_name}_view.js.coffee") - template "templates/model.jst", File.join(backbone_path, "templates", plural_name, "#{singular_name}.jst.ejs") + template "templates/model.haml", File.join(backbone_path, "templates", plural_name, "#{singular_name}.jst.ejs.haml") end - + protected def available_views %w(index show new edit) end - + end end -end \ No newline at end of file +end diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml new file mode 100644 index 0000000..30e825b --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -0,0 +1,14 @@ +%h1 Edit <%= singular_table_name %> + +%form#edit-<%= singular_table_name %>{:name => "<%= singular_table_name %>"} + +<% attributes.each do |attribute| -%> + .field + %label{:for => "<%= attribute.name %>"} <%= attribute.name %>: + = text_field_tag "<%= attribute.name %>", "<%%= <%= attribute.name %> %>".html_safe +<% end -%> + + .actions + %input{:type => "submit", :value => "Update <%= human_name %>"} + += link_to "Back", "#/index" diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.jst b/lib/generators/backbone/scaffold/templates/templates/edit.jst deleted file mode 100644 index a21d672..0000000 --- a/lib/generators/backbone/scaffold/templates/templates/edit.jst +++ /dev/null @@ -1,17 +0,0 @@ -

Edit <%= singular_table_name %>

- -
-<% attributes.each do |attribute| -%> -
- - %> > -
- -<% end -%> -
- -
- -
- -Back \ No newline at end of file diff --git a/lib/generators/backbone/scaffold/templates/templates/index.haml b/lib/generators/backbone/scaffold/templates/templates/index.haml new file mode 100644 index 0000000..eda960a --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/templates/index.haml @@ -0,0 +1,17 @@ +%h1 Listing <%= plural_table_name %> + +%table#<%= plural_name %>-table + %thead + %tr +<% attributes.each do |attribute| -%> + %th <%= attribute.human_name %> +<% end -%> + %th + %th + %th + + %tbody + +%br + += link_to "New <%= human_name %>", "#/new" diff --git a/lib/generators/backbone/scaffold/templates/templates/index.jst b/lib/generators/backbone/scaffold/templates/templates/index.jst deleted file mode 100644 index a18f7f7..0000000 --- a/lib/generators/backbone/scaffold/templates/templates/index.jst +++ /dev/null @@ -1,16 +0,0 @@ -

Listing <%= plural_table_name %>

- - - -<% attributes.each do |attribute| -%> - -<% end -%> - - - - -
<%= attribute.human_name %>
- -
- -New <%= human_name %> \ No newline at end of file diff --git a/lib/generators/backbone/scaffold/templates/templates/model.haml b/lib/generators/backbone/scaffold/templates/templates/model.haml new file mode 100644 index 0000000..ae65f89 --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/templates/model.haml @@ -0,0 +1,7 @@ +<% attributes.each do |attribute| -%> +%td <%%= <%= attribute.name %> %> +<% end -%> + +%td= link_to "Show", "#/<%%= id %>" +%td= link_to "Edit", "#/<%%= id %>/edit" +%td= link_to "Destroy", "#/<%%= id %>/destroy", :class => "destroy" diff --git a/lib/generators/backbone/scaffold/templates/templates/model.jst b/lib/generators/backbone/scaffold/templates/templates/model.jst deleted file mode 100644 index 207526a..0000000 --- a/lib/generators/backbone/scaffold/templates/templates/model.jst +++ /dev/null @@ -1,7 +0,0 @@ -<% attributes.each do |attribute| -%> -<%%= <%= attribute.name %> %> -<% end -%> - -Show -Edit -Destroy \ No newline at end of file diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml new file mode 100644 index 0000000..483df3f --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -0,0 +1,14 @@ +%h1 New <%= singular_table_name %> + +%form#new-<%= singular_table_name %>{:name => "<%= singular_table_name %>"} + +<% attributes.each do |attribute| -%> + .field + %label{:for => "<%= attribute.name %>"} <%= attribute.name %>: + = text_field_tag "<%= attribute.name %>", "<%%= <%= attribute.name %> %>".html_safe +<% end -%> + + .actions + %input{:type => "submit", :value => "Create <%= human_name %>"} + += link_to "Back", "#/index" diff --git a/lib/generators/backbone/scaffold/templates/templates/new.jst b/lib/generators/backbone/scaffold/templates/templates/new.jst deleted file mode 100644 index fd19bde..0000000 --- a/lib/generators/backbone/scaffold/templates/templates/new.jst +++ /dev/null @@ -1,17 +0,0 @@ -

New <%= singular_table_name %>

- -
-<% attributes.each do |attribute| -%> -
- - %> > -
- -<% end -%> -
- -
- -
- -Back \ No newline at end of file diff --git a/lib/generators/backbone/scaffold/templates/templates/show.jst b/lib/generators/backbone/scaffold/templates/templates/show.haml similarity index 52% rename from lib/generators/backbone/scaffold/templates/templates/show.jst rename to lib/generators/backbone/scaffold/templates/templates/show.haml index 06ff380..46f9fcc 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.jst +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -1,9 +1,7 @@ <% attributes.each do |attribute| -%> -

- <%= attribute.human_name %>: +%p + %strong <%= attribute.human_name %>: <%%= <%= attribute.name %> %> -

- <% end -%> -Back \ No newline at end of file += link_to "Back", "#/index" From a3113cec50bc0d588c1b4d5c1b487cb7de8c6d02 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Tue, 20 Sep 2011 17:12:51 -0500 Subject: [PATCH 02/78] Added haml_assets dependency to convert haml templates in templates JST --- backbone-rails.gemspec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backbone-rails.gemspec b/backbone-rails.gemspec index abbdfaa..6832bfe 100644 --- a/backbone-rails.gemspec +++ b/backbone-rails.gemspec @@ -6,14 +6,15 @@ Gem::Specification.new do |s| s.authors = ["Ryan Fitzgerald", "Code Brew Studios"] s.email = ["ryan@codebrewstudios.com"] s.homepage = "http://github.com/codebrew/backbone-rails" - + s.summary = "Use backbone.js with rails 3.1" s.description = "Quickly setup backbone.js for use with rails 3.1. Generators are provided to quickly get started." s.files = Dir["lib/**/*"] + Dir["vendor/**/*"] + ["MIT-LICENSE", "Rakefile", "README.md"] - + s.add_dependency('rails', '~> 3.1.0') s.add_dependency('coffee-script', '~> 2.2.0') s.add_dependency('ejs', '~> 1.0.0') - + s.add_dependency('haml_assets', '~> 0.0.3') + s.require_paths = ['lib'] end From 6a6d6a6aa4306771a4aa7103addbb04faa8b7cff Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Tue, 20 Sep 2011 17:33:39 -0500 Subject: [PATCH 03/78] Added html_safe in model template links --- .../backbone/scaffold/templates/templates/model.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/model.haml b/lib/generators/backbone/scaffold/templates/templates/model.haml index ae65f89..74ff392 100644 --- a/lib/generators/backbone/scaffold/templates/templates/model.haml +++ b/lib/generators/backbone/scaffold/templates/templates/model.haml @@ -2,6 +2,6 @@ %td <%%= <%= attribute.name %> %> <% end -%> -%td= link_to "Show", "#/<%%= id %>" -%td= link_to "Edit", "#/<%%= id %>/edit" -%td= link_to "Destroy", "#/<%%= id %>/destroy", :class => "destroy" +%td= link_to "Show", "#/<%%= id %>".html_safe +%td= link_to "Edit", "#/<%%= id %>/edit".html_safe +%td= link_to "Destroy", "#/<%%= id %>/destroy".html_safe, :class => "destroy" From f0f227d038f798f735d55ed6c1ebef1403e3f7b8 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 29 Sep 2011 16:01:48 -0500 Subject: [PATCH 04/78] Remove ejs and haml dependencies && Added jquery.tmpl into install generator --- backbone-rails.gemspec | 2 - .../backbone/install/install_generator.rb | 29 +- .../backbone/install/templates/app.coffee | 3 +- vendor/assets/javascripts/jquery.tmpl.js | 504 ++++++++++++++++++ 4 files changed, 523 insertions(+), 15 deletions(-) create mode 100644 vendor/assets/javascripts/jquery.tmpl.js diff --git a/backbone-rails.gemspec b/backbone-rails.gemspec index 6832bfe..307d1de 100644 --- a/backbone-rails.gemspec +++ b/backbone-rails.gemspec @@ -13,8 +13,6 @@ Gem::Specification.new do |s| s.add_dependency('rails', '~> 3.1.0') s.add_dependency('coffee-script', '~> 2.2.0') - s.add_dependency('ejs', '~> 1.0.0') - s.add_dependency('haml_assets', '~> 0.0.3') s.require_paths = ['lib'] end diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 1b1f59a..ab4a77c 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -4,31 +4,38 @@ module Backbone module Generators class InstallGenerator < Rails::Generators::Base include Backbone::Generators::ResourceHelpers - + source_root File.expand_path("../templates", __FILE__) - + desc "This generator installs backbone.js with a default folder layout in app/assets/javascripts/backbone" - + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, :desc => "Skip Git ignores and keeps" - + def inject_backbone inject_into_file "app/assets/javascripts/application.js", :before => "//= require_tree" do - "//= require underscore\n//= require backbone\n//= require backbone_rails_sync\n//= require backbone_datalink\n//= require backbone/#{application_name.underscore}\n" + files <<-EOF + //= require jquery.tmpl\n + //= require underscore\n + //= require backbone\n + //= require backbone_rails_sync\n + //= require backbone_datalink\n + //= require backbone/#{application_name.underscore}\n" + EOF end end - + def create_dir_layout - %W{routers models views templates}.each do |dir| - empty_directory "app/assets/javascripts/backbone/#{dir}" + %W{routers models views}.each do |dir| + empty_directory "app/assets/javascripts/backbone/#{dir}" create_file "app/assets/javascripts/backbone/#{dir}/.gitkeep" unless options[:skip_git] end end - + def create_app_file template "app.coffee", "app/assets/javascripts/backbone/#{application_name.underscore}.js.coffee" end - + end end -end \ No newline at end of file +end diff --git a/lib/generators/backbone/install/templates/app.coffee b/lib/generators/backbone/install/templates/app.coffee index 7f2568d..40357c5 100644 --- a/lib/generators/backbone/install/templates/app.coffee +++ b/lib/generators/backbone/install/templates/app.coffee @@ -1,5 +1,4 @@ #= require_self -#= require_tree ./templates #= require_tree ./models #= require_tree ./views #= require_tree ./routers @@ -8,4 +7,4 @@ window.<%= js_app_name %> = Models: {} Collections: {} Routers: {} - Views: {} \ No newline at end of file + Views: {} diff --git a/vendor/assets/javascripts/jquery.tmpl.js b/vendor/assets/javascripts/jquery.tmpl.js new file mode 100644 index 0000000..742b73d --- /dev/null +++ b/vendor/assets/javascripts/jquery.tmpl.js @@ -0,0 +1,504 @@ +/*! + * jQuery Templates Plugin + * http://github.com/jquery/jquery-tmpl + * + * Copyright Software Freedom Conservancy, Inc. + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + */ +(function( jQuery, undefined ){ + var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, + newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; + + function newTmplItem( options, parentItem, fn, data ) { + // Returns a template item data structure for a new rendered instance of a template (a 'template item'). + // The content field is a hierarchical array of strings and nested items (to be + // removed and replaced by nodes field of dom elements, once inserted in DOM). + + var newItem = { + data: data || (parentItem ? parentItem.data : {}), + _wrap: parentItem ? parentItem._wrap : null, + tmpl: null, + parent: parentItem || null, + nodes: [], + calls: tiCalls, + nest: tiNest, + wrap: tiWrap, + html: tiHtml, + update: tiUpdate + }; + if ( options ) { + jQuery.extend( newItem, options, { nodes: [], parent: parentItem } ); + } + if ( fn ) { + // Build the hierarchical content to be used during insertion into DOM + newItem.tmpl = fn; + newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); + newItem.key = ++itemKey; + // Keep track of new template item, until it is stored as jQuery Data on DOM element + (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; + } + return newItem; + } + + // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). + jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" + }, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, + parent = this.length === 1 && this[0].parentNode; + + appendToTmplItems = newTmplItems || {}; + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + ret = this; + } else { + for ( i = 0, l = insert.length; i < l; i++ ) { + cloneIndex = i; + elems = (i > 0 ? this.clone(true) : this).get(); + jQuery.fn[ original ].apply( jQuery(insert[i]), elems ); + ret = ret.concat( elems ); + } + cloneIndex = 0; + ret = this.pushStack( ret, name, insert.selector ); + } + tmplItems = appendToTmplItems; + appendToTmplItems = null; + jQuery.tmpl.complete( tmplItems ); + return ret; + }; + }); + + jQuery.fn.extend({ + // Use first wrapped element as template markup. + // Return wrapped set of template items, obtained by rendering template against data. + tmpl: function( data, options, parentItem ) { + return jQuery.tmpl( this[0], data, options, parentItem ); + }, + + // Find which rendered template item the first wrapped DOM element belongs to + tmplItem: function() { + return jQuery.tmplItem( this[0] ); + }, + + tmplElement: function() { + return jQuery.tmplElement( this[0] ); + }, + + // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. + template: function( name ) { + return jQuery.template( name, this[0] ); + }, + + domManip: function( args, table, callback, options ) { + // This appears to be a bug in the appendTo, etc. implementation + // it should be doing .call() instead of .apply(). See #6227 + if ( args[0] && args[0].nodeType ) { + var dmArgs = jQuery.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem; + while ( i < argsLength && !(tmplItem = jQuery.data( args[i++], "tmplItem" ))) {} + if ( argsLength > 1 ) { + dmArgs[0] = [jQuery.makeArray( args )]; + } + if ( tmplItem && cloneIndex ) { + dmArgs[2] = function( fragClone ) { + // Handler called by oldManip when rendered template has been inserted into DOM. + jQuery.tmpl.afterManip( this, fragClone, callback ); + }; + } + oldManip.apply( this, dmArgs ); + } else { + oldManip.apply( this, arguments ); + } + cloneIndex = 0; + if ( !appendToTmplItems ) { + jQuery.tmpl.complete( newTmplItems ); + } + return this; + } + }); + + jQuery.extend({ + // Return wrapped set of template items, obtained by rendering template against data. + tmpl: function( tmpl, data, options, parentItem ) { + var ret, topLevel = !parentItem; + if ( topLevel ) { + // This is a top-level tmpl call (not from a nested template using {{tmpl}}) + parentItem = topTmplItem; + if ( typeof tmpl != "function" ) + tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl ); + wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level + } else if ( !tmpl ) { + // The template item is already associated with DOM - this is a refresh. + // Re-evaluate rendered template for the parentItem + tmpl = parentItem.tmpl; + newTmplItems[parentItem.key] = parentItem; + parentItem.nodes = []; + if ( parentItem.wrapped ) { + updateWrapped( parentItem, parentItem.wrapped ); + } + // Rebuild, without creating a new template item + return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); + } + if ( !tmpl ) { + return []; // Could throw... + } + if ( typeof data === "function" ) { + data = data.call( parentItem || {} ); + } + if ( options && options.wrapped ) { + updateWrapped( options, options.wrapped ); + } + ret = jQuery.isArray( data ) ? + jQuery.map( data, function( dataItem ) { + return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; + }) : + [ newTmplItem( options, parentItem, tmpl, data ) ]; + return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; + }, + + // Return rendered template item for an element. + tmplItem: function( elem ) { + var tmplItem; + if ( elem instanceof jQuery ) { + elem = elem[0]; + } + while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} + return tmplItem || topTmplItem; + }, + + tmplElement: function( elem ) { + var tmplItem; + if ( elem instanceof jQuery ) { + elem = elem[0]; + } + while ( elem && elem.nodeType === 1 && !jQuery.data( elem, "tmplItem" ) && (elem = elem.parentNode) ) {} + return elem; + }, + + // Set: + // Use $.template( name, tmpl ) to cache a named template, + // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. + // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. + + // Get: + // Use $.template( name ) to access a cached template. + // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) + // will return the compiled template, without adding a name reference. + // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent + // to $.template( null, templateString ) + template: function( name, tmpl ) { + if (tmpl) { + // Compile template and associate with name + if ( typeof tmpl === "string" ) { + // This is an HTML string being passed directly in. + tmpl = buildTmplFn( tmpl ) + } else if ( tmpl instanceof jQuery ) { + tmpl = tmpl[0] || {}; + } + if ( tmpl.nodeType ) { + // If this is a template block, use cached copy, or generate tmpl function and cache. + tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); + } + return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl; + } + // Return named compiled template + return name ? (typeof name !== "string" ? jQuery.template( null, name ): + (jQuery.template[name] || + // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) + jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; + }, + + encode: function( text ) { + // Do HTML encoding replacing < > & and ' and " by corresponding entities. + return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); + } + }); + + jQuery.extend( jQuery.tmpl, { + tag: { + "tmpl": { + _default: { $2: "null" }, + open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" + // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) + // This means that {{tmpl foo}} treats foo as a template (which IS a function). + // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. + }, + "wrap": { + _default: { $2: "null" }, + open: "$item.calls(_,$1,$2);_=[];", + close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" + }, + "each": { + _default: { $2: "$index, $value" }, + open: "if($notnull_1){$.each($1a,function($2){with(this){", + close: "}});}" + }, + "if": { + open: "if(($notnull_1) && $1a){", + close: "}" + }, + "else": { + _default: { $1: "true" }, + open: "}else if(($notnull_1) && $1a){" + }, + "html": { + // Unecoded expression evaluation. + open: "if($notnull_1){_.push($1a);}" + }, + "=": { + // Encoded expression evaluation. Abbreviated form is ${}. + _default: { $1: "$data" }, + open: "if($notnull_1){_.push($.encode($1a));}" + }, + "!": { + // Comment tag. Skipped by parser + open: "" + } + }, + + // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events + complete: function( items ) { + newTmplItems = {}; + }, + + // Call this from code which overrides domManip, or equivalent + // Manage cloning/storing template items etc. + afterManip: function afterManip( elem, fragClone, callback ) { + // Provides cloned fragment ready for fixup prior to and after insertion into DOM + var content = fragClone.nodeType === 11 ? + jQuery.makeArray(fragClone.childNodes) : + fragClone.nodeType === 1 ? [fragClone] : []; + + // Return fragment to original caller (e.g. append) for DOM insertion + callback.call( elem, fragClone ); + + // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data. + storeTmplItems( content ); + cloneIndex++; + } + }); + + //========================== Private helper functions, used by code above ========================== + + function build( tmplItem, nested, content ) { + // Convert hierarchical content into flat string array + // and finally return array of fragments ready for DOM insertion + var frag, ret = content ? jQuery.map( content, function( item ) { + return (typeof item === "string") ? + // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM. + (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : + // This is a child template item. Build nested template. + build( item, tmplItem, item._ctnt ); + }) : + // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. + tmplItem; + if ( nested ) { + return ret; + } + + // top-level template + ret = ret.join(""); + + // Support templates which have initial or final text nodes, or consist only of text + // Also support HTML entities within the HTML markup. + ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { + frag = jQuery( middle ).get(); + + storeTmplItems( frag ); + if ( before ) { + frag = unencode( before ).concat(frag); + } + if ( after ) { + frag = frag.concat(unencode( after )); + } + }); + return frag ? frag : unencode( ret ); + } + + function unencode( text ) { + // Use createElement, since createTextNode will not render HTML entities correctly + var el = document.createElement( "div" ); + el.innerHTML = text; + return jQuery.makeArray(el.childNodes); + } + + // Generate a reusable function that will serve to render a template against data + function buildTmplFn( markup ) { + return new Function("jQuery","$item", + "var $=jQuery,call,_=[],$data=$item.data;" + + + // Introduce the data as local variables using with(){} + "with($data){_.push('" + + + // Convert the template into pure JavaScript + jQuery.trim(markup) + .replace( /([\\'])/g, "\\$1" ) + .replace( /[\r\t\n]/g, " " ) + .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) + .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, + function( all, slash, type, fnargs, target, parens, args ) { + var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect; + if ( !tag ) { + throw "Template command not found: " + type; + } + def = tag._default || []; + if ( parens && !/\w$/.test(target)) { + target += parens; + parens = ""; + } + if ( target ) { + target = unescape( target ); + args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); + // Support for target being things like a.toLowerCase(); + // In that case don't call with template item as 'this' pointer. Just evaluate... + expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($data" + args)) : target; + exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; + } else { + exprAutoFnDetect = expr = def.$1 || "null"; + } + fnargs = unescape( fnargs ); + return "');" + + tag[ slash ? "close" : "open" ] + .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) + .split( "$1a" ).join( exprAutoFnDetect ) + .split( "$1" ).join( expr ) + .split( "$2" ).join( fnargs ? + fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) { + params = params ? ("," + params + ")") : (parens ? ")" : ""); + return params ? ("(" + name + ").call($item" + params) : all; + }) + : (def.$2||"") + ) + + "_.push('"; + }) + + "');}return _;" + ); + } + function updateWrapped( options, wrapped ) { + // Build the wrapped content. + options._wrap = build( options, true, + // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. + jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] + ).join(""); + } + + function unescape( args ) { + return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; + } + function outerHtml( elem ) { + var div = document.createElement("div"); + div.appendChild( elem.cloneNode(true) ); + return div.innerHTML; + } + + // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance. + function storeTmplItems( content ) { + var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; + for ( i = 0, l = content.length; i < l; i++ ) { + if ( (elem = content[i]).nodeType !== 1 ) { + continue; + } + elems = elem.getElementsByTagName("*"); + for ( m = elems.length - 1; m >= 0; m-- ) { + processItemKey( elems[m] ); + } + processItemKey( elem ); + } + function processItemKey( el ) { + var pntKey, pntNode = el, pntItem, tmplItem, key; + // Ensure that each rendered template inserted into the DOM has its own template item, + if ( (key = el.getAttribute( tmplItmAtt ))) { + while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } + if ( pntKey !== key ) { + // The next ancestor with a _tmplitem expando is on a different key than this one. + // So this is a top-level element within this template item + // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment. + pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0; + if ( !(tmplItem = newTmplItems[key]) ) { + // The item is for wrapped content, and was copied from the temporary parent wrappedItem. + tmplItem = wrappedItems[key]; + tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true ); + tmplItem.key = ++itemKey; + newTmplItems[itemKey] = tmplItem; + } + if ( cloneIndex ) { + cloneTmplItem( key ); + } + } + el.removeAttribute( tmplItmAtt ); + } else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) { + // This was a rendered element, cloned during append or appendTo etc. + // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. + cloneTmplItem( tmplItem.key ); + newTmplItems[tmplItem.key] = tmplItem; + pntNode = jQuery.data( el.parentNode, "tmplItem" ); + pntNode = pntNode ? pntNode.key : 0; + } + if ( tmplItem ) { + pntItem = tmplItem; + // Find the template item of the parent element. + // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) + while ( pntItem && pntItem.key != pntNode ) { + // Add this element as a top-level node for this rendered template item, as well as for any + // ancestor items between this item and the item of its parent element + pntItem.nodes.push( el ); + pntItem = pntItem.parent; + } + // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... + delete tmplItem._ctnt; + delete tmplItem._wrap; + // Store template item as jQuery data on the element + jQuery.data( el, "tmplItem", tmplItem ); + } + function cloneTmplItem( key ) { + key = key + keySuffix; + tmplItem = newClonedItems[key] = + (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true )); + } + } + } + + //---- Helper functions for template item ---- + + function tiCalls( content, tmpl, data, options ) { + if ( !content ) { + return stack.pop(); + } + stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); + } + + function tiNest( tmpl, data, options ) { + // nested template, using {{tmpl}} tag + return jQuery.tmpl( jQuery.template( tmpl ), data, options, this ); + } + + function tiWrap( call, wrapped ) { + // nested template, using {{wrap}} tag + var options = call.options || {}; + options.wrapped = wrapped; + // Apply the template, which may incorporate wrapped content, + return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item ); + } + + function tiHtml( filter, textOnly ) { + var wrapped = this._wrap; + return jQuery.map( + jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), + function(e) { + return textOnly ? + e.innerText || e.textContent : + e.outerHTML || outerHtml(e); + }); + } + + function tiUpdate() { + var coll = this.nodes; + jQuery.tmpl( null, null, null, this).insertBefore( coll[0] ); + jQuery( coll ).remove(); + } +})( jQuery ); \ No newline at end of file From c2de80a97fcbdac0a278a413074501d27efc20eb Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 30 Sep 2011 12:19:13 -0500 Subject: [PATCH 05/78] changed haml templates for working with jquery tmpl && generated rails model when use backbone model generate && generated inherited resources controller when use backbone scaffold --- .../backbone/install/install_generator.rb | 16 ++++---- .../backbone/model/model_generator.rb | 17 ++++++--- lib/generators/backbone/resource_helpers.rb | 38 ++++++++++++------- .../backbone/router/router_generator.rb | 26 ++++++------- .../backbone/router/templates/router.coffee | 4 +- .../backbone/router/templates/template.haml | 2 + .../backbone/router/templates/template.jst | 2 - .../backbone/router/templates/view.coffee | 4 +- .../backbone/scaffold/scaffold_generator.rb | 16 +++++++- .../backbone/scaffold/templates/controller.rb | 4 ++ .../backbone/scaffold/templates/index.haml | 14 +++++++ .../backbone/scaffold/templates/router.coffee | 16 ++++---- .../scaffold/templates/templates/edit.haml | 13 +------ .../scaffold/templates/templates/form.haml | 10 +++++ .../scaffold/templates/templates/model.haml | 8 ++-- .../scaffold/templates/templates/new.haml | 13 +------ .../scaffold/templates/templates/show.haml | 4 +- .../scaffold/templates/views/edit_view.coffee | 2 +- .../templates/views/index_view.coffee | 2 +- .../templates/views/model_view.coffee | 2 +- .../scaffold/templates/views/new_view.coffee | 2 +- .../scaffold/templates/views/show_view.coffee | 2 +- 22 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 lib/generators/backbone/router/templates/template.haml delete mode 100644 lib/generators/backbone/router/templates/template.jst create mode 100644 lib/generators/backbone/scaffold/templates/controller.rb create mode 100644 lib/generators/backbone/scaffold/templates/index.haml create mode 100644 lib/generators/backbone/scaffold/templates/templates/form.haml diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index ab4a77c..1096cda 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -14,14 +14,14 @@ class InstallGenerator < Rails::Generators::Base def inject_backbone inject_into_file "app/assets/javascripts/application.js", :before => "//= require_tree" do - files <<-EOF - //= require jquery.tmpl\n - //= require underscore\n - //= require backbone\n - //= require backbone_rails_sync\n - //= require backbone_datalink\n - //= require backbone/#{application_name.underscore}\n" - EOF + [ + "//= require jquery.tmpl", + "//= require underscore", + "//= require backbone", + "//= require backbone_rails_sync", + "//= require backbone_datalink", + "//= require backbone/#{application_name.underscore}" + ].join("\n") end end diff --git a/lib/generators/backbone/model/model_generator.rb b/lib/generators/backbone/model/model_generator.rb index ee1d487..e934849 100644 --- a/lib/generators/backbone/model/model_generator.rb +++ b/lib/generators/backbone/model/model_generator.rb @@ -4,16 +4,21 @@ module Backbone module Generators class ModelGenerator < Rails::Generators::NamedBase include Backbone::Generators::ResourceHelpers - + source_root File.expand_path("../templates", __FILE__) - desc "This generator creates a backbone model" - + desc "This generator creates a backbone model and rails model with migration" + argument :attributes, :type => :array, :default => [], :banner => "field:type field:type" - + def create_backbone_model template "model.coffee", "#{backbone_path}/models/#{file_name}.js.coffee" end - + + def create_rails_model + attrs = attributes.collect{|a| "#{a.name}:#{a.type}" }.join(" ") + generate "model #{name} #{attrs}" + end + end end -end \ No newline at end of file +end diff --git a/lib/generators/backbone/resource_helpers.rb b/lib/generators/backbone/resource_helpers.rb index a5e985d..859d9c6 100644 --- a/lib/generators/backbone/resource_helpers.rb +++ b/lib/generators/backbone/resource_helpers.rb @@ -1,43 +1,55 @@ module Backbone module Generators module ResourceHelpers - + def backbone_path "app/assets/javascripts/backbone" end - + + def backbone_tmpl_path + "app/views" + end + + def controllers_path + "app/controllers" + end + def model_namespace [js_app_name, "Models", class_name].join(".") end - + def singular_model_name uncapitalize singular_name.camelize end - + def plural_model_name uncapitalize(plural_name.camelize) end - + def collection_namespace [js_app_name, "Collections", plural_name.camelize].join(".") end - + def view_namespace [js_app_name, "Views", plural_name.camelize].join(".") end - + def router_namespace [js_app_name, "Routers", plural_name.camelize].join(".") end - + def jst(action) "backbone/templates/#{plural_name}/#{action}" end - + + def tmpl(action) + "backbone_templates_#{plural_name}_#{action}".camelize(:lower) + end + def js_app_name application_name.camelize end - + def application_name if defined?(Rails) && Rails.application Rails.application.class.name.split('::').first @@ -45,11 +57,11 @@ def application_name "application" end end - + def uncapitalize(str) str[0, 1].downcase + str[1..-1] end - + end end -end \ No newline at end of file +end diff --git a/lib/generators/backbone/router/router_generator.rb b/lib/generators/backbone/router/router_generator.rb index 2f5c045..161c8ad 100644 --- a/lib/generators/backbone/router/router_generator.rb +++ b/lib/generators/backbone/router/router_generator.rb @@ -4,17 +4,17 @@ module Backbone module Generators class RouterGenerator < Rails::Generators::NamedBase include Backbone::Generators::ResourceHelpers - + source_root File.expand_path("../templates", __FILE__) desc "This generator creates a backbone router with views and templates for the provided actions" - + argument :actions, :type => :array, :default => [], :banner => "action action" - + RESERVED_JS_WORDS = %W{ - break case catch continue debugger default delete do else finally for - function if in instanceof new return switch this throw try typeof var void while with + break case catch continue debugger default delete do else finally for + function if in instanceof new return switch this throw try typeof var void while with } - + def validate_no_reserved_words actions.each do |action| if RESERVED_JS_WORDS.include? action @@ -23,22 +23,22 @@ def validate_no_reserved_words end end end - - def create_router_files + + def create_router_files template 'router.coffee', File.join(backbone_path, "routers", class_path, "#{file_name}_router.js.coffee") end - + def create_view_files actions.each do |action| @action = action @view_path = File.join(backbone_path, "views", plural_name, "#{action}_view.js.coffee") - @jst_path = File.join(backbone_path,"templates", plural_name, "#{action}.jst.ejs") - + @tmpl_path = File.join(backbone_tmpl_path, plural_name, "_#{action}.html.haml") + template "view.coffee", @view_path - template "template.jst", @jst_path + template "template.haml", @tmpl_path end end end end -end \ No newline at end of file +end diff --git a/lib/generators/backbone/router/templates/router.coffee b/lib/generators/backbone/router/templates/router.coffee index f250a94..40798e0 100644 --- a/lib/generators/backbone/router/templates/router.coffee +++ b/lib/generators/backbone/router/templates/router.coffee @@ -8,7 +8,7 @@ class <%= router_namespace %>Router extends Backbone.Router <% actions.each do |action| -%> <%= action %>: -> - @view = new <%= "#{view_namespace}.#{action.camelize}View()" %> - $("#<%= plural_name %>").html(@view.render().el) + @<%= action %>_view = new <%= "#{view_namespace}.#{action.camelize}View()" %> + $("#<%= plural_name %>").html(@<%= action %>_view.render().el) <% end -%> diff --git a/lib/generators/backbone/router/templates/template.haml b/lib/generators/backbone/router/templates/template.haml new file mode 100644 index 0000000..5ebb621 --- /dev/null +++ b/lib/generators/backbone/router/templates/template.haml @@ -0,0 +1,2 @@ +%h1 <%= class_name %>#<%= @action %> +%p Find me in <%= @tmpl_path %> diff --git a/lib/generators/backbone/router/templates/template.jst b/lib/generators/backbone/router/templates/template.jst deleted file mode 100644 index d28b30f..0000000 --- a/lib/generators/backbone/router/templates/template.jst +++ /dev/null @@ -1,2 +0,0 @@ -

<%= class_name %>#<%= @action %>

-

Find me in <%= @jst_path %>

\ No newline at end of file diff --git a/lib/generators/backbone/router/templates/view.coffee b/lib/generators/backbone/router/templates/view.coffee index 1059706..aa4e0aa 100644 --- a/lib/generators/backbone/router/templates/view.coffee +++ b/lib/generators/backbone/router/templates/view.coffee @@ -1,8 +1,8 @@ <%= view_namespace %> ||= {} class <%= view_namespace %>.<%= @action.camelize %>View extends Backbone.View - template: JST["<%= jst @action %>"] + template: () -> $("#<%= tmpl @action %>").tmpl() render: -> $(@el).html(@template()) - return this + @ diff --git a/lib/generators/backbone/scaffold/scaffold_generator.rb b/lib/generators/backbone/scaffold/scaffold_generator.rb index 3449895..dd585c5 100644 --- a/lib/generators/backbone/scaffold/scaffold_generator.rb +++ b/lib/generators/backbone/scaffold/scaffold_generator.rb @@ -7,6 +7,12 @@ class ScaffoldGenerator < ModelGenerator source_root File.expand_path("../templates", __FILE__) desc "This generator creates the client side crud scaffolding" + def inject_into_routes + inject_into_file "config/routes.rb", :after => "Application.routes.draw do\n" do + "\n resources :#{plural_name}\n" + end + end + def create_router_files template 'router.coffee', File.join(backbone_path, "routers", class_path, "#{plural_name}_router.js.coffee") end @@ -14,11 +20,17 @@ def create_router_files def create_view_files available_views.each do |view| template "views/#{view}_view.coffee", File.join(backbone_path, "views", plural_name, "#{view}_view.js.coffee") - template "templates/#{view}.haml", File.join(backbone_path, "templates", plural_name, "#{view}.jst.ejs.haml") + template "templates/#{view}.haml", File.join(backbone_tmpl_path, plural_name, "_#{view}.html.haml") end template "views/model_view.coffee", File.join(backbone_path, "views", plural_name, "#{singular_name}_view.js.coffee") - template "templates/model.haml", File.join(backbone_path, "templates", plural_name, "#{singular_name}.jst.ejs.haml") + template "templates/model.haml", File.join(backbone_tmpl_path, plural_name, "_#{singular_name}.html.haml") + template "templates/form.haml", File.join(backbone_tmpl_path, plural_name, "_form.html.haml") + template "index.haml", File.join(backbone_tmpl_path, plural_name, "index.html.haml") + end + + def create_rails_controller + template "controller.rb", File.join(controllers_path, "#{plural_name}_controller.rb") end protected diff --git a/lib/generators/backbone/scaffold/templates/controller.rb b/lib/generators/backbone/scaffold/templates/controller.rb new file mode 100644 index 0000000..5da6292 --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/controller.rb @@ -0,0 +1,4 @@ +class <%= plural_name.camelize %>Controller < InheritedResources::Base + respond_to :json +end + diff --git a/lib/generators/backbone/scaffold/templates/index.haml b/lib/generators/backbone/scaffold/templates/index.haml new file mode 100644 index 0000000..02e762b --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/index.haml @@ -0,0 +1,14 @@ +#<%= plural_name %> + +:javascript + $(function() { + window.router = new <%= router_namespace %>Router({ <%= plural_name %>: #{ @<%= plural_name %>.to_json.html_safe } }); + Backbone.history.start(); + }); + +- content_for :templates do + = script_template("index") + = script_template("new") + = script_template("show") + = script_template("edit") + = script_template("<%= singular_name %>") diff --git a/lib/generators/backbone/scaffold/templates/router.coffee b/lib/generators/backbone/scaffold/templates/router.coffee index 4320d9f..cf060a5 100644 --- a/lib/generators/backbone/scaffold/templates/router.coffee +++ b/lib/generators/backbone/scaffold/templates/router.coffee @@ -11,21 +11,21 @@ class <%= router_namespace %>Router extends Backbone.Router ".*" : "index" new<%= class_name %>: -> - @view = new <%= "#{view_namespace}.NewView(collection: @#{plural_name})" %> - $("#<%= plural_name %>").html(@view.render().el) + @new_view = new <%= "#{view_namespace}.NewView(collection: @#{plural_name})" %> + $("#<%= plural_name %>").html(@new_view.render().el) index: -> - @view = new <%= "#{view_namespace}.IndexView(#{plural_name}: @#{plural_name})" %> - $("#<%= plural_name %>").html(@view.render().el) + @index_view = new <%= "#{view_namespace}.IndexView(#{plural_name}: @#{plural_name})" %> + $("#<%= plural_name %>").html(@index_view.render().el) show: (id) -> <%= singular_name %> = @<%= plural_name %>.get(id) - @view = new <%= "#{view_namespace}.ShowView(model: #{singular_name})" %> - $("#<%= plural_name %>").html(@view.render().el) + @show_view = new <%= "#{view_namespace}.ShowView(model: #{singular_name})" %> + $("#<%= plural_name %>").html(@show_view.render().el) edit: (id) -> <%= singular_name %> = @<%= plural_name %>.get(id) - @view = new <%= "#{view_namespace}.EditView(model: #{singular_name})" %> - $("#<%= plural_name %>").html(@view.render().el) + @edit_view = new <%= "#{view_namespace}.EditView(model: #{singular_name})" %> + $("#<%= plural_name %>").html(@edit_view.render().el) diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml index 30e825b..dbffbcd 100644 --- a/lib/generators/backbone/scaffold/templates/templates/edit.haml +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -1,14 +1,5 @@ %h1 Edit <%= singular_table_name %> -%form#edit-<%= singular_table_name %>{:name => "<%= singular_table_name %>"} += render "form" -<% attributes.each do |attribute| -%> - .field - %label{:for => "<%= attribute.name %>"} <%= attribute.name %>: - = text_field_tag "<%= attribute.name %>", "<%%= <%= attribute.name %> %>".html_safe -<% end -%> - - .actions - %input{:type => "submit", :value => "Update <%= human_name %>"} - -= link_to "Back", "#/index" += link_to t("links.back"), "#/index" diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml new file mode 100644 index 0000000..666cea1 --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -0,0 +1,10 @@ += form_for :<%= singular_table_name %>, :url => "", :html => { :id => "edit-<%= singular_table_name %>" } do |f| + +<% attributes.each do |attribute| -%> + .field + = f.label :<%= attribute.name %> + = f.text_field :<%= attribute.name %>, :value => "${<%= attribute.name %>}" +<% end -%> + + .actions + = f.submit diff --git a/lib/generators/backbone/scaffold/templates/templates/model.haml b/lib/generators/backbone/scaffold/templates/templates/model.haml index 74ff392..e496950 100644 --- a/lib/generators/backbone/scaffold/templates/templates/model.haml +++ b/lib/generators/backbone/scaffold/templates/templates/model.haml @@ -1,7 +1,7 @@ <% attributes.each do |attribute| -%> -%td <%%= <%= attribute.name %> %> +%td ${<%= attribute.name %>} <% end -%> -%td= link_to "Show", "#/<%%= id %>".html_safe -%td= link_to "Edit", "#/<%%= id %>/edit".html_safe -%td= link_to "Destroy", "#/<%%= id %>/destroy".html_safe, :class => "destroy" +%td= link_to "Show", "#/${id}".html_safe +%td= link_to "Edit", "#/${id}/edit".html_safe +%td= link_to "Destroy", "#/${id}/destroy".html_safe, :class => "destroy" diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml index 483df3f..fb6d714 100644 --- a/lib/generators/backbone/scaffold/templates/templates/new.haml +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -1,14 +1,5 @@ %h1 New <%= singular_table_name %> -%form#new-<%= singular_table_name %>{:name => "<%= singular_table_name %>"} += render "form" -<% attributes.each do |attribute| -%> - .field - %label{:for => "<%= attribute.name %>"} <%= attribute.name %>: - = text_field_tag "<%= attribute.name %>", "<%%= <%= attribute.name %> %>".html_safe -<% end -%> - - .actions - %input{:type => "submit", :value => "Create <%= human_name %>"} - -= link_to "Back", "#/index" += link_to t("links.back"), "#/index" diff --git a/lib/generators/backbone/scaffold/templates/templates/show.haml b/lib/generators/backbone/scaffold/templates/templates/show.haml index 46f9fcc..20a17d7 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.haml +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -1,7 +1,7 @@ <% attributes.each do |attribute| -%> %p %strong <%= attribute.human_name %>: - <%%= <%= attribute.name %> %> + ${<%= attribute.name %>} <% end -%> -= link_to "Back", "#/index" += link_to t("links.back"), "#/index" diff --git a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee index 00d5172..e797960 100644 --- a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee @@ -1,7 +1,7 @@ <%= view_namespace %> ||= {} class <%= view_namespace %>.EditView extends Backbone.View - template : JST["<%= jst 'edit' %>"] + template: (data) -> $("#<%= tmpl 'edit' %>").tmpl(data) events : "submit #edit-<%= singular_name %>" : "update" diff --git a/lib/generators/backbone/scaffold/templates/views/index_view.coffee b/lib/generators/backbone/scaffold/templates/views/index_view.coffee index e51339d..69648f6 100644 --- a/lib/generators/backbone/scaffold/templates/views/index_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/index_view.coffee @@ -1,7 +1,7 @@ <%= view_namespace %> ||= {} class <%= view_namespace %>.IndexView extends Backbone.View - template: JST["<%= jst 'index' %>"] + template: (data) -> $("#<%= tmpl 'index' %>").tmpl(data) initialize: () -> _.bindAll(this, 'addOne', 'addAll', 'render') diff --git a/lib/generators/backbone/scaffold/templates/views/model_view.coffee b/lib/generators/backbone/scaffold/templates/views/model_view.coffee index 3289537..25b5472 100644 --- a/lib/generators/backbone/scaffold/templates/views/model_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/model_view.coffee @@ -1,7 +1,7 @@ <%= view_namespace %> ||= {} class <%= view_namespace %>.<%= singular_name.camelize %>View extends Backbone.View - template: JST["<%= jst singular_name %>"] + template: (data) -> $("#<%= tmpl singular_name %>").tmpl(data) events: "click .destroy" : "destroy" diff --git a/lib/generators/backbone/scaffold/templates/views/new_view.coffee b/lib/generators/backbone/scaffold/templates/views/new_view.coffee index 1905439..c99812f 100644 --- a/lib/generators/backbone/scaffold/templates/views/new_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/new_view.coffee @@ -1,7 +1,7 @@ <%= view_namespace %> ||= {} class <%= view_namespace %>.NewView extends Backbone.View - template: JST["<%= jst 'new' %>"] + template: (data) -> $("#<%= tmpl 'new' %>").tmpl(data) events: "submit #new-<%= singular_name %>": "save" diff --git a/lib/generators/backbone/scaffold/templates/views/show_view.coffee b/lib/generators/backbone/scaffold/templates/views/show_view.coffee index e26ca7d..5e9cc74 100644 --- a/lib/generators/backbone/scaffold/templates/views/show_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/show_view.coffee @@ -1,7 +1,7 @@ <%= view_namespace %> ||= {} class <%= view_namespace %>.ShowView extends Backbone.View - template: JST["<%= jst 'show' %>"] + template: (data) -> $("#<%= tmpl 'show' %>").tmpl(data) render: -> $(this.el).html(@template(@model.toJSON() )) From a1c5d7ac4ad7d9fc6dc60c7717a5cdc744dee883 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 30 Sep 2011 12:30:56 -0500 Subject: [PATCH 06/78] backbone_datalinks.js file was modified to support the names of rails text_fields included nested names --- .../assets/javascripts/backbone_datalink.js | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index 15683c6..4b1763a 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -1,7 +1,33 @@ (function($) { + + function setValues(el, model){ + var attrs = {}; + var nestedName = el.attr("name"); + var nesteds = nestedName.split("[") + var nestedObject = null; + + for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") + var name = nesteds[nesteds.length-1]; + + for (var i in nesteds) { + var value = nesteds[i]; + nestedObject = nestedObject == null ? model : nestedObject; + if ( /^.+_attributes$/.test(value) ) { + value = value.replace("_attributes", ""); + nestedObject = nestedObject[value]; + } else if ( /^backboneCid_.+$/.test(value) ) { + value = value.replace("backboneCid_", ""); + nestedObject = nestedObject.getByCid(value) + } + } + attrs[name] = el.val(); + nestedObject.set(attrs); + return true; + } + return $.extend($.fn, { backboneLink: function(model) { - return $(this).find(":input").each(function() { + $(this).find(":input").each(function() { var el, name; el = $(this); name = el.attr("name"); @@ -9,13 +35,11 @@ return el.val(model.get(name)); }); return $(this).bind("change", function() { - var attrs; el = $(this); - attrs = {}; - attrs[el.attr("name")] = el.val(); - return model.set(attrs); + return setValues(el, model); }); }); + return $(this); } }); })(jQuery); From 331628c625e97e25c5ac2fb7edb117766f2549bc Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 30 Sep 2011 12:58:45 -0500 Subject: [PATCH 07/78] Fixed bug with FORM ID in views templates --- lib/generators/backbone/scaffold/templates/templates/edit.haml | 2 +- lib/generators/backbone/scaffold/templates/templates/form.haml | 2 +- lib/generators/backbone/scaffold/templates/templates/new.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml index dbffbcd..0f08166 100644 --- a/lib/generators/backbone/scaffold/templates/templates/edit.haml +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -1,5 +1,5 @@ %h1 Edit <%= singular_table_name %> -= render "form" += render :partial => "form", :locals => { :form_id => "edit-<%= singular_table_name %>" } = link_to t("links.back"), "#/index" diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml index 666cea1..fb37d8f 100644 --- a/lib/generators/backbone/scaffold/templates/templates/form.haml +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -1,4 +1,4 @@ -= form_for :<%= singular_table_name %>, :url => "", :html => { :id => "edit-<%= singular_table_name %>" } do |f| += form_for :<%= singular_table_name %>, :url => "", :html => { :id => form_id } do |f| <% attributes.each do |attribute| -%> .field diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml index fb6d714..2fbab6b 100644 --- a/lib/generators/backbone/scaffold/templates/templates/new.haml +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -1,5 +1,5 @@ %h1 New <%= singular_table_name %> -= render "form" += render :partial => "form", :locals => { :form_id => "new-<%= singular_table_name %>" } = link_to t("links.back"), "#/index" From af15e09028a96d3d7a730f6737e298b52b382944 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 30 Sep 2011 17:21:54 -0500 Subject: [PATCH 08/78] The templates tags were adapted to use bootstrap styles --- lib/generators/backbone/resource_helpers.rb | 8 +++++ .../scaffold/templates/templates/edit.haml | 12 +++++-- .../scaffold/templates/templates/form.haml | 19 +++++++----- .../scaffold/templates/templates/index.haml | 31 ++++++++++--------- .../scaffold/templates/templates/model.haml | 7 +++-- .../scaffold/templates/templates/new.haml | 12 +++++-- .../templates/templates/pagination.haml | 18 +++++++++++ .../scaffold/templates/templates/show.haml | 28 ++++++++++++++--- 8 files changed, 100 insertions(+), 35 deletions(-) create mode 100644 lib/generators/backbone/scaffold/templates/templates/pagination.haml diff --git a/lib/generators/backbone/resource_helpers.rb b/lib/generators/backbone/resource_helpers.rb index 859d9c6..ac431d4 100644 --- a/lib/generators/backbone/resource_helpers.rb +++ b/lib/generators/backbone/resource_helpers.rb @@ -18,6 +18,14 @@ def model_namespace [js_app_name, "Models", class_name].join(".") end + def classify_model_name + singular_name.classify + end + + def human_attribute_translate(name) + "#{classify_model_name}.human_attribute_name(:#{name})" + end + def singular_model_name uncapitalize singular_name.camelize end diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml index 0f08166..4445f8f 100644 --- a/lib/generators/backbone/scaffold/templates/templates/edit.haml +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -1,5 +1,11 @@ -%h1 Edit <%= singular_table_name %> +.row + .page-header + %h1= t(".title", :name => @<%= singular_model_name %>) -= render :partial => "form", :locals => { :form_id => "edit-<%= singular_table_name %>" } +.row + .span16.columns + %ul.tabs + %li + = link_to t("links.back"), "#/index" -= link_to t("links.back"), "#/index" += render :partial => "form", :locals => { :form_id => "edit-<%= singular_table_name %>" } diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml index fb37d8f..ef2f3f4 100644 --- a/lib/generators/backbone/scaffold/templates/templates/form.haml +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -1,10 +1,13 @@ -= form_for :<%= singular_table_name %>, :url => "", :html => { :id => form_id } do |f| - +.row + .span16.columns + = form_for :<%= singular_table_name %>, :url => "", :html => { :id => form_id } do |f| + %fieldset <% attributes.each do |attribute| -%> - .field - = f.label :<%= attribute.name %> - = f.text_field :<%= attribute.name %>, :value => "${<%= attribute.name %>}" -<% end -%> + .clearfix + = f.label :<%= attribute.name %> + .input + = f.text_field :<%= attribute.name %>, :value => "${<%= attribute.name %>}", :class => "xlarge" - .actions - = f.submit +<% end -%> + .actions + = f.submit :class => "btn primary" diff --git a/lib/generators/backbone/scaffold/templates/templates/index.haml b/lib/generators/backbone/scaffold/templates/templates/index.haml index eda960a..ca45d10 100644 --- a/lib/generators/backbone/scaffold/templates/templates/index.haml +++ b/lib/generators/backbone/scaffold/templates/templates/index.haml @@ -1,17 +1,20 @@ -%h1 Listing <%= plural_table_name %> +.row + .span16.columns + .page-header + %h1= t(".title") +.row + .span16.columns + %ul.tabs + %li + = link_to t("links.new", :resource => <%= classify_model_name %>.model_name.human), "#/new" -%table#<%= plural_name %>-table - %thead - %tr +.row + .span16.columns + %table#<%= plural_name %>-table.zebra-striped + %thead + %tr <% attributes.each do |attribute| -%> - %th <%= attribute.human_name %> + %th= <%= human_attribute_translate(attribute.name) %> <% end -%> - %th - %th - %th - - %tbody - -%br - -= link_to "New <%= human_name %>", "#/new" + %th + %tbody diff --git a/lib/generators/backbone/scaffold/templates/templates/model.haml b/lib/generators/backbone/scaffold/templates/templates/model.haml index e496950..603e2ce 100644 --- a/lib/generators/backbone/scaffold/templates/templates/model.haml +++ b/lib/generators/backbone/scaffold/templates/templates/model.haml @@ -2,6 +2,7 @@ %td ${<%= attribute.name %>} <% end -%> -%td= link_to "Show", "#/${id}".html_safe -%td= link_to "Edit", "#/${id}/edit".html_safe -%td= link_to "Destroy", "#/${id}/destroy".html_safe, :class => "destroy" +%td.links + = link_to "Show", "#/${id}".html_safe, :class => "show" + = link_to "Edit", "#/${id}/edit".html_safe, :class => "edit" + = link_to "Destroy", "#/${id}/destroy".html_safe, :class => "destroy" diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml index 2fbab6b..c5dcb8e 100644 --- a/lib/generators/backbone/scaffold/templates/templates/new.haml +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -1,5 +1,11 @@ -%h1 New <%= singular_table_name %> +.row + .page-header + %h1= t(".title") -= render :partial => "form", :locals => { :form_id => "new-<%= singular_table_name %>" } +.row + .span16.columns + %ul.tabs + %li + = link_to t("links.back"), "#/index" -= link_to t("links.back"), "#/index" += render :partial => "form", :locals => { :form_id => "new-<%= singular_table_name %>" } diff --git a/lib/generators/backbone/scaffold/templates/templates/pagination.haml b/lib/generators/backbone/scaffold/templates/templates/pagination.haml new file mode 100644 index 0000000..d4d950f --- /dev/null +++ b/lib/generators/backbone/scaffold/templates/templates/pagination.haml @@ -0,0 +1,18 @@ +.row + %hr + .pagination + %ul + %li.prev.disabled + %a{:href => "#"} ← Previous + %li.active + %a{:href => "#"} 1 + %li + %a{:href => "#"} 2 + %li + %a{:href => "#"} 3 + %li + %a{:href => "#"} 4 + %li + %a{:href => "#"} 5 + %li.next + %a{:href => "#"} → Previous diff --git a/lib/generators/backbone/scaffold/templates/templates/show.haml b/lib/generators/backbone/scaffold/templates/templates/show.haml index 20a17d7..e9f10b3 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.haml +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -1,7 +1,27 @@ +.row + .page-header + %h1= t(".title") + +.row + .span16.columns + %ul.tabs + %li + = link_to t("links.back"), "#/index" + +.row + .span10.columns <% attributes.each do |attribute| -%> -%p - %strong <%= attribute.human_name %>: - ${<%= attribute.name %>} + %p + %strong <%= attribute.human_name %>: + ${<%= attribute.name %>} + <% end -%> -= link_to t("links.back"), "#/index" + .span6.columns + .dashboard + .page-header + %h3 + %p + + + From 01212af4892c65f70fe716fefd31d015839738f0 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 30 Sep 2011 17:37:06 -0500 Subject: [PATCH 09/78] Added inherited_resources gem as mandatory --- backbone-rails.gemspec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backbone-rails.gemspec b/backbone-rails.gemspec index 307d1de..e9e9802 100644 --- a/backbone-rails.gemspec +++ b/backbone-rails.gemspec @@ -11,8 +11,9 @@ Gem::Specification.new do |s| s.description = "Quickly setup backbone.js for use with rails 3.1. Generators are provided to quickly get started." s.files = Dir["lib/**/*"] + Dir["vendor/**/*"] + ["MIT-LICENSE", "Rakefile", "README.md"] - s.add_dependency('rails', '~> 3.1.0') - s.add_dependency('coffee-script', '~> 2.2.0') + s.add_dependency('rails', '~> 3.1') + s.add_dependency('coffee-script', '~> 2.2') + s.add_dependency('inherited_resources', '~> 1.3') s.require_paths = ['lib'] end From d740bb299f9937d93b744c4abe41d04558604f68 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 30 Sep 2011 18:01:57 -0500 Subject: [PATCH 10/78] fiexed bug with classify_model_name in resource_helpers --- lib/generators/backbone/resource_helpers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/generators/backbone/resource_helpers.rb b/lib/generators/backbone/resource_helpers.rb index ac431d4..f1a6d6f 100644 --- a/lib/generators/backbone/resource_helpers.rb +++ b/lib/generators/backbone/resource_helpers.rb @@ -19,7 +19,7 @@ def model_namespace end def classify_model_name - singular_name.classify + singular_model_name.camelize end def human_attribute_translate(name) From 29c556217141b292f890dcd07a018cc5034cf92c Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Sat, 1 Oct 2011 09:58:41 -0500 Subject: [PATCH 11/78] Inject script_template method into ApplicationHelpers when run install generator --- .../backbone/install/install_generator.rb | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 1096cda..c752a20 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -20,11 +20,30 @@ def inject_backbone "//= require backbone", "//= require backbone_rails_sync", "//= require backbone_datalink", - "//= require backbone/#{application_name.underscore}" + "//= require backbone/#{application_name.underscore}\n" ].join("\n") end end + def inject_in_application_helper + inject_into_file "app/helpers/application_helper.rb", :after => "module ApplicationHelper" do + [ + "\n", + "def script_template(*args)", + " name = args.first", + " options = args.second || {}", + " id = options[:id] || \"backbone_templates_\#{controller_name}_\#{name}\"", + " locals = options[:locals] || {}", + " partial = options[:partial] || \"\#{controller_name}/\#{name}\"", + " id = id.camelize(:lower)", + " content_tag(:script, :type => \"text/template\", :id => id) do", + " render :partial => partial, :locals => locals", + " end", + "end\n" + ].join("\n ") + end + end + def create_dir_layout %W{routers models views}.each do |dir| empty_directory "app/assets/javascripts/backbone/#{dir}" From 6869204b5a1a759c588766a1ddcb864b2b26a574 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Sat, 1 Oct 2011 10:37:14 -0500 Subject: [PATCH 12/78] Added columns container for page-header in show template file --- .../backbone/scaffold/templates/templates/show.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/show.haml b/lib/generators/backbone/scaffold/templates/templates/show.haml index e9f10b3..cdc1a26 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.haml +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -1,6 +1,7 @@ .row - .page-header - %h1= t(".title") + .span16.columns + .page-header + %h1= t(".title") .row .span16.columns From 5bf0b45cea8e5e58b8bdbdf57b11f4fda53d6b21 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Sat, 1 Oct 2011 13:19:00 -0500 Subject: [PATCH 13/78] Fixed a bug in form_for, the translator now works correctly --- lib/generators/backbone/scaffold/templates/templates/form.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml index ef2f3f4..d543cf5 100644 --- a/lib/generators/backbone/scaffold/templates/templates/form.haml +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -1,6 +1,6 @@ .row .span16.columns - = form_for :<%= singular_table_name %>, :url => "", :html => { :id => form_id } do |f| + = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => form_id } do |f| %fieldset <% attributes.each do |attribute| -%> .clearfix From 9021316e80d26bfbdf812ac116377aaf0e4e6cb3 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Sat, 1 Oct 2011 19:55:31 -0500 Subject: [PATCH 14/78] Fixed bug in submit button --- .../backbone/scaffold/templates/templates/edit.haml | 6 ++++-- .../backbone/scaffold/templates/templates/form.haml | 4 ++-- .../backbone/scaffold/templates/templates/new.haml | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml index 4445f8f..6f5c2cc 100644 --- a/lib/generators/backbone/scaffold/templates/templates/edit.haml +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -1,6 +1,8 @@ .row .page-header - %h1= t(".title", :name => @<%= singular_model_name %>) + %h1 + = t(".title") + ${<%= attributes.first.try(:name) %>} .row .span16.columns @@ -8,4 +10,4 @@ %li = link_to t("links.back"), "#/index" -= render :partial => "form", :locals => { :form_id => "edit-<%= singular_table_name %>" } += render :partial => "form", :locals => { :form_type => "edit" } diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml index d543cf5..9479f17 100644 --- a/lib/generators/backbone/scaffold/templates/templates/form.haml +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -1,6 +1,6 @@ .row .span16.columns - = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => form_id } do |f| + = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => "#{form_type}-<%= singular_table_name %>" } do |f| %fieldset <% attributes.each do |attribute| -%> .clearfix @@ -10,4 +10,4 @@ <% end -%> .actions - = f.submit :class => "btn primary" + = f.submit t("helpers.submit.#{form_type}", :model => f.object.class.model_name.human), :class => "btn primary" diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml index c5dcb8e..7e6b747 100644 --- a/lib/generators/backbone/scaffold/templates/templates/new.haml +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -8,4 +8,4 @@ %li = link_to t("links.back"), "#/index" -= render :partial => "form", :locals => { :form_id => "new-<%= singular_table_name %>" } += render :partial => "form", :locals => { :form_type => "new" } From d8430f650ce7881aafcdf953acb7fbcebe099dfd Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Sat, 1 Oct 2011 20:12:42 -0500 Subject: [PATCH 15/78] Added columns container for page-header in new and edit template file --- .../backbone/scaffold/templates/templates/edit.haml | 9 +++++---- .../backbone/scaffold/templates/templates/new.haml | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml index 6f5c2cc..b5d3488 100644 --- a/lib/generators/backbone/scaffold/templates/templates/edit.haml +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -1,8 +1,9 @@ .row - .page-header - %h1 - = t(".title") - ${<%= attributes.first.try(:name) %>} + .span16.columns + .page-header + %h1 + = t(".title") + ${<%= attributes.first.try(:name) %>} .row .span16.columns diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml index 7e6b747..9f80eb3 100644 --- a/lib/generators/backbone/scaffold/templates/templates/new.haml +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -1,6 +1,7 @@ .row - .page-header - %h1= t(".title") + .span16.columns + .page-header + %h1= t(".title") .row .span16.columns From b590019fd37e3916b38be48d20c38dd84c08dc19 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 3 Oct 2011 13:12:20 -0500 Subject: [PATCH 16/78] Fixed bug to prevent calls propagations to addAll in collection reset --- lib/generators/backbone/scaffold/templates/router.coffee | 1 + .../backbone/scaffold/templates/views/index_view.coffee | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/lib/generators/backbone/scaffold/templates/router.coffee b/lib/generators/backbone/scaffold/templates/router.coffee index cf060a5..b27e1ea 100644 --- a/lib/generators/backbone/scaffold/templates/router.coffee +++ b/lib/generators/backbone/scaffold/templates/router.coffee @@ -15,6 +15,7 @@ class <%= router_namespace %>Router extends Backbone.Router $("#<%= plural_name %>").html(@new_view.render().el) index: -> + @index_view.remove() if @index_view? @index_view = new <%= "#{view_namespace}.IndexView(#{plural_name}: @#{plural_name})" %> $("#<%= plural_name %>").html(@index_view.render().el) diff --git a/lib/generators/backbone/scaffold/templates/views/index_view.coffee b/lib/generators/backbone/scaffold/templates/views/index_view.coffee index 69648f6..fcddf80 100644 --- a/lib/generators/backbone/scaffold/templates/views/index_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/index_view.coffee @@ -20,3 +20,7 @@ class <%= view_namespace %>.IndexView extends Backbone.View @addAll() return this + + remove: -> + @options.<%= plural_model_name %>.unbind('reset', @addAll) + super() From 31047027f91347d62248ee807cd687923ad0a38c Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 3 Oct 2011 13:33:02 -0500 Subject: [PATCH 17/78] Added I18n support in show template view --- lib/generators/backbone/scaffold/templates/templates/show.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/show.haml b/lib/generators/backbone/scaffold/templates/templates/show.haml index cdc1a26..580a877 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.haml +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -13,7 +13,7 @@ .span10.columns <% attributes.each do |attribute| -%> %p - %strong <%= attribute.human_name %>: + %strong= <%= human_attribute_translate(attribute.name) %> ${<%= attribute.name %>} <% end -%> From 94c3bcccacabfc8a1bea407109e7e18e7de57630 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 3 Oct 2011 13:47:21 -0500 Subject: [PATCH 18/78] Added I18n support in actions links (show, edit, destroy) --- .../backbone/scaffold/templates/templates/model.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/model.haml b/lib/generators/backbone/scaffold/templates/templates/model.haml index 603e2ce..2032924 100644 --- a/lib/generators/backbone/scaffold/templates/templates/model.haml +++ b/lib/generators/backbone/scaffold/templates/templates/model.haml @@ -3,6 +3,6 @@ <% end -%> %td.links - = link_to "Show", "#/${id}".html_safe, :class => "show" - = link_to "Edit", "#/${id}/edit".html_safe, :class => "edit" - = link_to "Destroy", "#/${id}/destroy".html_safe, :class => "destroy" + = link_to t("links.show"), "#/${id}".html_safe, :class => "show" + = link_to t("links.edit"), "#/${id}/edit".html_safe, :class => "edit" + = link_to t("links.destroy"), "#/${id}/destroy".html_safe, :class => "destroy" From 965cd30859bc9b96ecce64a794c9bb1eac006f26 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 12:06:25 -0500 Subject: [PATCH 19/78] Added BaseModel file --- .../backbone/install/install_generator.rb | 4 +++ .../backbone/install/templates/app.coffee | 3 ++ .../install/templates/base_model.coffee | 32 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 lib/generators/backbone/install/templates/base_model.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index c752a20..59d850e 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -55,6 +55,10 @@ def create_app_file template "app.coffee", "app/assets/javascripts/backbone/#{application_name.underscore}.js.coffee" end + def create_base_model_file + template "base_model.coffee", "app/assets/javascripts/backbone/models/base_model.js.coffee" + end + end end end diff --git a/lib/generators/backbone/install/templates/app.coffee b/lib/generators/backbone/install/templates/app.coffee index 40357c5..f73b57c 100644 --- a/lib/generators/backbone/install/templates/app.coffee +++ b/lib/generators/backbone/install/templates/app.coffee @@ -1,5 +1,8 @@ #= require_self +#= require ./helpers +#= require ./models/base_model #= require_tree ./models +#= require ./views/base_view #= require_tree ./views #= require_tree ./routers diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee new file mode 100644 index 0000000..5f5a23e --- /dev/null +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -0,0 +1,32 @@ +class <%= js_app_name %>.Models.BaseModel extends Backbone.Model + + validates: (attrs, validates = {}) -> + resultMessage = {} + messages = <%= js_app_name %>.Helpers.errorsMessages + + _.each(attrs, (value, key) -> + values = _.compact( (validates[key] ||= "").split(" ") ) + + for value in values + + switch value + when "presence" + if _.isEmpty( $.trim( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.blank) + + when "numericality" + unless (/^\d+\.?\d+$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.not_a_number) + + else false + ) + + if _.isEmpty(resultMessage) + delete @errors + null + else + @attributes = _.extend(@attributes, attrs) + @errors = resultMessage + + isValid: () -> + if @validate(@attributes)? then false else true From 612452365bdb4a431e97923d255e537e8c1efb4a Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 12:09:01 -0500 Subject: [PATCH 20/78] Added Helpers file --- .../backbone/install/install_generator.rb | 4 ++ .../backbone/install/templates/helpers.coffee | 58 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 lib/generators/backbone/install/templates/helpers.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 59d850e..70dac6e 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -55,6 +55,10 @@ def create_app_file template "app.coffee", "app/assets/javascripts/backbone/#{application_name.underscore}.js.coffee" end + def create_helpers_file + template "helpers.coffee", "app/assets/javascripts/backbone/helpers.js.coffee" + end + def create_base_model_file template "base_model.coffee", "app/assets/javascripts/backbone/models/base_model.js.coffee" end diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee new file mode 100644 index 0000000..a0276de --- /dev/null +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -0,0 +1,58 @@ +<%= js_app_name %>.Helpers = + + jsonData: (url, params = {}) -> + return if !url + responseDate = null + $.ajax( + url: url + async: false + dataType: "json" + data: params + success: (data, textStatus, jqXHR) -> responseDate = data + ) + responseDate + + jsonCallback: (url, callback, params = {}) -> + $.getJSON(url, params, (data) -> callback?(data) ) + + # Renders For Alers Messages + renderWarnings: (data) -> + $("#alerts_container").html( $("#backboneWarningAlert").tmpl(data) ) + + renderErrors: (data) -> + $("#alerts_container").html( $("#backboneErrorAlert").tmpl(data) ) + + renderSuccess: (data) -> + $("#alerts_container").html( $("#backboneSuccessAlert").tmpl(data) ) + + renderInfo: (data) -> + $("#alerts_container").html( $("#backboneInfoAlert").tmpl(data) ) + + errorsMessages: + inclusion: "no está incluído en la lista" + exclusion: "está reservado" + invalid: "es inválido" + record_invalid: "es inválido" + invalid_date: "es una fecha inválida" + confirmation: "no coincide con la confirmación" + blank: "no puede estar en blanco" + empty: "no puede estar vacío" + not_a_number: "no es un número" + taken: "ya ha sido tomado" + less_than: "debe ser menor que %{count}" + less_than_or_equal_to: "debe ser menor o igual que %{count}" + greater_than: "debe ser mayor que %{count}" + greater_than_or_equal_to: "debe ser mayor o igual que %{count}" + too_short: + one: "es demasiado corto (mínimo 1 caracter)" + other: "es demasiado corto (mínimo %{count} caracteres)" + too_long: + one: "es demasiado largo (máximo 1 caracter)" + other: "es demasiado largo (máximo %{count} caracteres)" + equal_to: "debe ser igual a %{count}" + wrong_length: + one: "longitud errónea (debe ser de 1 caracter)" + other: "longitud errónea (debe ser de %{count} caracteres)" + accepted: "debe ser aceptado" + even: "debe ser un número par" + odd: "debe ser un número non" From ca724e7f27acace38a148f3c434c6b18816ed82e Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 12:38:20 -0500 Subject: [PATCH 21/78] Added BaseView file --- .../backbone/install/install_generator.rb | 4 ++ .../install/templates/base_view.coffee | 61 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 lib/generators/backbone/install/templates/base_view.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 70dac6e..19d8fdb 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -63,6 +63,10 @@ def create_base_model_file template "base_model.coffee", "app/assets/javascripts/backbone/models/base_model.js.coffee" end + def create_base_view_file + template "base_view.coffee", "app/assets/javascripts/backbone/views/base_view.js.coffee" + end + end end end diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee new file mode 100644 index 0000000..ca9dbb8 --- /dev/null +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -0,0 +1,61 @@ +class <%= js_app_name %>.Views.BaseView extends Backbone.View + + # Defaults Events + events: + "click .destroy" : "destroy" + + destroy: (e, options = {}) -> + msg = $(e.currentTarget).attr("data-confirm") + if msg? and !confirm(msg) then return false + + @model.destroy(options) + @remove() + + return false + + save: (e, options = {}) -> + e.preventDefault() + e.stopPropagation() + + msg = $(e.currentTarget).attr("confirm") + if msg? and !confirm(msg) then return false + + options = _.extend( + success: (model) => + @model = model + window.location.hash = "/#{@model.id}" + error: (model, jqXHR) => + @renderErrors( model, $.parseJSON( jqXHR.responseText ) ) + + options) + + if @model.isValid() then @collection.create(@model, options) + else @renderErrors(@model, @model.errors) + + update : (e, options = {}) -> + e.preventDefault() + e.stopPropagation() + + msg = $(e.currentTarget).attr("confirm") + if msg? and !confirm(msg) then return false + + options = _.extend( + success : (model) => + @model = model + window.location.hash = "/#{@model.id}" + error: (model, jqXHR) => + @renderErrors( model, $.parseJSON( jqXHR.responseText ) ) + + options) + + if @model.isValid() then @model.save(null, options) + else @renderErrors(@model, @model.errors) + + renderErrors: (model, errors) -> + fullErrors = {} + _.each(errors, (messages, key) -> + name = $('label[for="' + model.paramRoot + '_' + key + '"]').text() || key + for message in messages + (fullErrors.errors ||= []).push({name: name, message: message}) + ) + <%= js_app_name %>.Helpers.renderErrors(fullErrors) From eeced220afdc87a53570a8f8498310643c5f1e58 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 13:03:35 -0500 Subject: [PATCH 22/78] Added validations example in model template && Now Models extends from BaseModel --- lib/generators/backbone/model/templates/model.coffee | 8 +++++++- lib/generators/backbone/scaffold/templates/model.coffee | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/generators/backbone/model/templates/model.coffee b/lib/generators/backbone/model/templates/model.coffee index 930a0f8..c763032 100644 --- a/lib/generators/backbone/model/templates/model.coffee +++ b/lib/generators/backbone/model/templates/model.coffee @@ -1,4 +1,4 @@ -class <%= model_namespace %> extends Backbone.Model +class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel paramRoot: '<%= singular_table_name %>' defaults: @@ -6,6 +6,12 @@ class <%= model_namespace %> extends Backbone.Model <%= attribute.name %>: null <% end -%> + validate: (attrs) -> + return @validates(attrs, { + # example: : "presence" + }) + + class <%= collection_namespace %>Collection extends Backbone.Collection model: <%= model_namespace %> url: '<%= route_url %>' diff --git a/lib/generators/backbone/scaffold/templates/model.coffee b/lib/generators/backbone/scaffold/templates/model.coffee index 930a0f8..c763032 100644 --- a/lib/generators/backbone/scaffold/templates/model.coffee +++ b/lib/generators/backbone/scaffold/templates/model.coffee @@ -1,4 +1,4 @@ -class <%= model_namespace %> extends Backbone.Model +class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel paramRoot: '<%= singular_table_name %>' defaults: @@ -6,6 +6,12 @@ class <%= model_namespace %> extends Backbone.Model <%= attribute.name %>: null <% end -%> + validate: (attrs) -> + return @validates(attrs, { + # example: : "presence" + }) + + class <%= collection_namespace %>Collection extends Backbone.Collection model: <%= model_namespace %> url: '<%= route_url %>' From 395d97f386326088f625bf60e0e633004d993160 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 15:49:20 -0500 Subject: [PATCH 23/78] Modified views templates for Views extends from BaseView --- .../backbone/scaffold/templates/index.haml | 2 +- .../backbone/scaffold/templates/router.coffee | 9 ++--- .../scaffold/templates/views/edit_view.coffee | 29 +++++++--------- .../templates/views/index_view.coffee | 8 +++-- .../templates/views/model_view.coffee | 16 ++++----- .../scaffold/templates/views/new_view.coffee | 34 +++++-------------- .../scaffold/templates/views/show_view.coffee | 12 +++++-- 7 files changed, 49 insertions(+), 61 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/index.haml b/lib/generators/backbone/scaffold/templates/index.haml index 02e762b..641bf91 100644 --- a/lib/generators/backbone/scaffold/templates/index.haml +++ b/lib/generators/backbone/scaffold/templates/index.haml @@ -2,7 +2,7 @@ :javascript $(function() { - window.router = new <%= router_namespace %>Router({ <%= plural_name %>: #{ @<%= plural_name %>.to_json.html_safe } }); + window.router = new <%= router_namespace %>Router({ <%= plural_model_name %>: #{ @<%= plural_name %>.to_json.html_safe } }); Backbone.history.start(); }); diff --git a/lib/generators/backbone/scaffold/templates/router.coffee b/lib/generators/backbone/scaffold/templates/router.coffee index b27e1ea..8f06e10 100644 --- a/lib/generators/backbone/scaffold/templates/router.coffee +++ b/lib/generators/backbone/scaffold/templates/router.coffee @@ -11,22 +11,23 @@ class <%= router_namespace %>Router extends Backbone.Router ".*" : "index" new<%= class_name %>: -> - @new_view = new <%= "#{view_namespace}.NewView(collection: @#{plural_name})" %> + @new_view = new <%= "#{view_namespace}.NewView(collection: @#{plural_model_name})" %> $("#<%= plural_name %>").html(@new_view.render().el) index: -> @index_view.remove() if @index_view? - @index_view = new <%= "#{view_namespace}.IndexView(#{plural_name}: @#{plural_name})" %> + @index_view = new <%= "#{view_namespace}.IndexView(#{plural_model_name}: @#{plural_model_name})" %> $("#<%= plural_name %>").html(@index_view.render().el) show: (id) -> - <%= singular_name %> = @<%= plural_name %>.get(id) + <%= singular_name %> = @<%= plural_model_name %>.get(id) @show_view = new <%= "#{view_namespace}.ShowView(model: #{singular_name})" %> $("#<%= plural_name %>").html(@show_view.render().el) edit: (id) -> - <%= singular_name %> = @<%= plural_name %>.get(id) + <%= singular_name %> = @<%= plural_model_name %>.get(id) + @edit_view.remove() if @edit_view? @edit_view = new <%= "#{view_namespace}.EditView(model: #{singular_name})" %> $("#<%= plural_name %>").html(@edit_view.render().el) diff --git a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee index e797960..6f96c3c 100644 --- a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee @@ -1,24 +1,21 @@ <%= view_namespace %> ||= {} -class <%= view_namespace %>.EditView extends Backbone.View +class <%= view_namespace %>.EditView extends <%= js_app_name %>.Views.BaseView template: (data) -> $("#<%= tmpl 'edit' %>").tmpl(data) - events : - "submit #edit-<%= singular_name %>" : "update" + initialize: -> + @model.bind("error", @renderErrors) - update : (e) -> - e.preventDefault() - e.stopPropagation() - - @model.save(null, - success : (<%= singular_name %>) => - @model = <%= singular_name %> - window.location.hash = "/#{@model.id}" + events: + _.extend( _.clone(@__super__.events), + "submit #edit-<%= singular_name %>" : "update" ) - render : -> - $(this.el).html(this.template(@model.toJSON() )) - - this.$("form").backboneLink(@model) - + render: -> + $(@el).html( @template( @model.toJSON() ) ) + this.$("form#edit-<%= singular_name %>").backboneLink(@model) return this + + remove: -> + @model.unbind("error", @renderErrors) + super() diff --git a/lib/generators/backbone/scaffold/templates/views/index_view.coffee b/lib/generators/backbone/scaffold/templates/views/index_view.coffee index fcddf80..814f429 100644 --- a/lib/generators/backbone/scaffold/templates/views/index_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/index_view.coffee @@ -1,13 +1,17 @@ <%= view_namespace %> ||= {} -class <%= view_namespace %>.IndexView extends Backbone.View +class <%= view_namespace %>.IndexView extends <%= js_app_name %>.Views.BaseView template: (data) -> $("#<%= tmpl 'index' %>").tmpl(data) initialize: () -> _.bindAll(this, 'addOne', 'addAll', 'render') - @options.<%= plural_model_name %>.bind('reset', @addAll) + events: + _.extend( _.clone(@__super__.events), + {} + ) + addAll: () -> @options.<%= plural_model_name %>.each(@addOne) diff --git a/lib/generators/backbone/scaffold/templates/views/model_view.coffee b/lib/generators/backbone/scaffold/templates/views/model_view.coffee index 25b5472..bfc36a3 100644 --- a/lib/generators/backbone/scaffold/templates/views/model_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/model_view.coffee @@ -1,19 +1,15 @@ <%= view_namespace %> ||= {} -class <%= view_namespace %>.<%= singular_name.camelize %>View extends Backbone.View +class <%= view_namespace %>.<%= singular_name.camelize %>View extends <%= js_app_name%>.Views.BaseView template: (data) -> $("#<%= tmpl singular_name %>").tmpl(data) - events: - "click .destroy" : "destroy" - tagName: "tr" - destroy: () -> - @model.destroy() - this.remove() - - return false + events: + _.extend( _.clone(@__super__.events), + {} + ) render: -> - $(this.el).html(@template(@model.toJSON() )) + $(@el).html( @template( @model.toJSON() ) ) return this diff --git a/lib/generators/backbone/scaffold/templates/views/new_view.coffee b/lib/generators/backbone/scaffold/templates/views/new_view.coffee index c99812f..3640bc4 100644 --- a/lib/generators/backbone/scaffold/templates/views/new_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/new_view.coffee @@ -1,37 +1,19 @@ <%= view_namespace %> ||= {} -class <%= view_namespace %>.NewView extends Backbone.View +class <%= view_namespace %>.NewView extends <%= js_app_name %>.Views.BaseView template: (data) -> $("#<%= tmpl 'new' %>").tmpl(data) - events: - "submit #new-<%= singular_name %>": "save" - - constructor: (options) -> + initialize: (options) -> super(options) @model = new @collection.model() + @model.bind("error", @renderErrors) - @model.bind("change:errors", () => - this.render() - ) - - save: (e) -> - e.preventDefault() - e.stopPropagation() - - @model.unset("errors") - - @collection.create(@model.toJSON(), - success: (<%= singular_name %>) => - @model = <%= singular_name %> - window.location.hash = "/#{@model.id}" - - error: (<%= singular_name %>, jqXHR) => - @model.set({errors: $.parseJSON(jqXHR.responseText)}) + events: + _.extend( _.clone(@__super__.events), + "submit #new-<%= singular_name %>": "save" ) render: -> - $(this.el).html(@template(@model.toJSON() )) - - this.$("form").backboneLink(@model) - + $(@el).html( @template( @model.toJSON() ) ) + this.$("form#new-<%= singular_name %>").backboneLink(@model) return this diff --git a/lib/generators/backbone/scaffold/templates/views/show_view.coffee b/lib/generators/backbone/scaffold/templates/views/show_view.coffee index 5e9cc74..8530ac6 100644 --- a/lib/generators/backbone/scaffold/templates/views/show_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/show_view.coffee @@ -1,8 +1,16 @@ <%= view_namespace %> ||= {} -class <%= view_namespace %>.ShowView extends Backbone.View +class <%= view_namespace %>.ShowView extends <%= js_app_name %>.Views.BaseView template: (data) -> $("#<%= tmpl 'show' %>").tmpl(data) + events: + _.extend( _.clone(@__super__.events), + {} + ) + render: -> - $(this.el).html(@template(@model.toJSON() )) + $(@el).html( @template( @model.toJSON() ) ) return this + + destroy: (e) -> + super(e, success: () -> window.location.hash = "") From 0fe495558b21a1a6c071f34b4e89775e5d40a17a Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 16:00:05 -0500 Subject: [PATCH 24/78] Added links for edit and destroy in show template --- .../backbone/scaffold/templates/templates/show.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/show.haml b/lib/generators/backbone/scaffold/templates/templates/show.haml index 580a877..5d07841 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.haml +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -6,8 +6,9 @@ .row .span16.columns %ul.tabs - %li - = link_to t("links.back"), "#/index" + %li= link_to t("links.back"), "#/index" + %li= link_to t("links.edit"), "#/${id}/edit" + %li= link_to t("links.destroy"), "#/index", :class => "destroy", :confirm => t("links.confirm") .row .span10.columns From 61f54be497117c88b16adb4c4fdd2779882f55ad Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 16:08:33 -0500 Subject: [PATCH 25/78] Added confirm message for destroy links --- .../backbone/scaffold/templates/templates/form.haml | 2 +- .../backbone/scaffold/templates/templates/model.haml | 2 +- .../backbone/scaffold/templates/views/edit_view.coffee | 4 ++-- .../backbone/scaffold/templates/views/new_view.coffee | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml index 9479f17..a52a888 100644 --- a/lib/generators/backbone/scaffold/templates/templates/form.haml +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -1,6 +1,6 @@ .row .span16.columns - = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => "#{form_type}-<%= singular_table_name %>" } do |f| + = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => "#{form_type}_<%= singular_table_name %>" } do |f| %fieldset <% attributes.each do |attribute| -%> .clearfix diff --git a/lib/generators/backbone/scaffold/templates/templates/model.haml b/lib/generators/backbone/scaffold/templates/templates/model.haml index 2032924..e38edad 100644 --- a/lib/generators/backbone/scaffold/templates/templates/model.haml +++ b/lib/generators/backbone/scaffold/templates/templates/model.haml @@ -5,4 +5,4 @@ %td.links = link_to t("links.show"), "#/${id}".html_safe, :class => "show" = link_to t("links.edit"), "#/${id}/edit".html_safe, :class => "edit" - = link_to t("links.destroy"), "#/${id}/destroy".html_safe, :class => "destroy" + = link_to t("links.destroy"), "#/${id}/destroy".html_safe, :class => "destroy", :confirm => t("links.confirm") diff --git a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee index 6f96c3c..d01348d 100644 --- a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee @@ -8,12 +8,12 @@ class <%= view_namespace %>.EditView extends <%= js_app_name %>.Views.BaseView events: _.extend( _.clone(@__super__.events), - "submit #edit-<%= singular_name %>" : "update" + "submit #edit_<%= singular_name %>" : "update" ) render: -> $(@el).html( @template( @model.toJSON() ) ) - this.$("form#edit-<%= singular_name %>").backboneLink(@model) + this.$("form#edit_<%= singular_name %>").backboneLink(@model) return this remove: -> diff --git a/lib/generators/backbone/scaffold/templates/views/new_view.coffee b/lib/generators/backbone/scaffold/templates/views/new_view.coffee index 3640bc4..42edb31 100644 --- a/lib/generators/backbone/scaffold/templates/views/new_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/new_view.coffee @@ -10,10 +10,10 @@ class <%= view_namespace %>.NewView extends <%= js_app_name %>.Views.BaseView events: _.extend( _.clone(@__super__.events), - "submit #new-<%= singular_name %>": "save" + "submit #new_<%= singular_name %>": "save" ) render: -> $(@el).html( @template( @model.toJSON() ) ) - this.$("form#new-<%= singular_name %>").backboneLink(@model) + this.$("form#new_<%= singular_name %>").backboneLink(@model) return this From e85209d432230a927ccd03a00196f9cc6246fd65 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 17:08:41 -0500 Subject: [PATCH 26/78] Added Alerts Templates Views In Install Generator --- lib/generators/backbone/install/install_generator.rb | 8 ++++++++ .../backbone/install/templates/alerts/_error_alert.haml | 7 +++++++ .../backbone/install/templates/alerts/_info_alert.haml | 4 ++++ .../backbone/install/templates/alerts/_success_alert.haml | 4 ++++ .../backbone/install/templates/alerts/_warning_alert.haml | 4 ++++ 5 files changed, 27 insertions(+) create mode 100644 lib/generators/backbone/install/templates/alerts/_error_alert.haml create mode 100644 lib/generators/backbone/install/templates/alerts/_info_alert.haml create mode 100644 lib/generators/backbone/install/templates/alerts/_success_alert.haml create mode 100644 lib/generators/backbone/install/templates/alerts/_warning_alert.haml diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 19d8fdb..bdcb0e9 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -67,6 +67,14 @@ def create_base_view_file template "base_view.coffee", "app/assets/javascripts/backbone/views/base_view.js.coffee" end + def create_dir_backbone_alerts + empty_directory "app/views/backbone_alerts" + template "alerts/_error_alert.haml", "app/views/backbone_alerts/_error_alert.html.haml" + template "alerts/_info_alert.haml", "app/views/backbone_alerts/_info_alert.html.haml" + template "alerts/_success_alert.haml", "app/views/backbone_alerts/_success_alert.html.haml" + template "alerts/_warning_alert.haml", "app/views/backbone_alerts/_warning_alert.html.haml" + end + end end end diff --git a/lib/generators/backbone/install/templates/alerts/_error_alert.haml b/lib/generators/backbone/install/templates/alerts/_error_alert.haml new file mode 100644 index 0000000..cb9952c --- /dev/null +++ b/lib/generators/backbone/install/templates/alerts/_error_alert.haml @@ -0,0 +1,7 @@ +.alert-message.error + %a.close{:href =>"#"} x + + {{each errors}} + %p + %strong ${name} ${message} + {{/each}} diff --git a/lib/generators/backbone/install/templates/alerts/_info_alert.haml b/lib/generators/backbone/install/templates/alerts/_info_alert.haml new file mode 100644 index 0000000..8e2dcd8 --- /dev/null +++ b/lib/generators/backbone/install/templates/alerts/_info_alert.haml @@ -0,0 +1,4 @@ +.alert-message.warning + %a.close{:href =>"#"} x + %p + %strong Ocurrio un super info diff --git a/lib/generators/backbone/install/templates/alerts/_success_alert.haml b/lib/generators/backbone/install/templates/alerts/_success_alert.haml new file mode 100644 index 0000000..5ee1a32 --- /dev/null +++ b/lib/generators/backbone/install/templates/alerts/_success_alert.haml @@ -0,0 +1,4 @@ +.alert-message.warning + %a.close{:href =>"#"} x + %p + %strong Ocurrio un super success diff --git a/lib/generators/backbone/install/templates/alerts/_warning_alert.haml b/lib/generators/backbone/install/templates/alerts/_warning_alert.haml new file mode 100644 index 0000000..33371c4 --- /dev/null +++ b/lib/generators/backbone/install/templates/alerts/_warning_alert.haml @@ -0,0 +1,4 @@ +.alert-message.warning + %a.close{:href =>"#"} x + %p + %strong Ocurrio un super warning From b95d7bcb62bd1c996ce573d4915395651e1d5e8c Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 6 Oct 2011 17:58:54 -0500 Subject: [PATCH 27/78] Fixed bug with singular_table_name in Forms Ids templates --- lib/generators/backbone/scaffold/templates/model.coffee | 2 +- lib/generators/backbone/scaffold/templates/templates/form.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/model.coffee b/lib/generators/backbone/scaffold/templates/model.coffee index c763032..fe0be31 100644 --- a/lib/generators/backbone/scaffold/templates/model.coffee +++ b/lib/generators/backbone/scaffold/templates/model.coffee @@ -1,5 +1,5 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel - paramRoot: '<%= singular_table_name %>' + paramRoot: '<%= singular_name %>' defaults: <% attributes.each do |attribute| -%> diff --git a/lib/generators/backbone/scaffold/templates/templates/form.haml b/lib/generators/backbone/scaffold/templates/templates/form.haml index a52a888..0432c1e 100644 --- a/lib/generators/backbone/scaffold/templates/templates/form.haml +++ b/lib/generators/backbone/scaffold/templates/templates/form.haml @@ -1,6 +1,6 @@ .row .span16.columns - = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => "#{form_type}_<%= singular_table_name %>" } do |f| + = form_for <%= classify_model_name %>.new, :url => "", :html => { :id => "#{form_type}_<%= singular_name %>" } do |f| %fieldset <% attributes.each do |attribute| -%> .clearfix From 06ee7589a2c85ef9a8f9d35daba557822ab6fd4d Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 7 Oct 2011 10:14:40 -0500 Subject: [PATCH 28/78] Added Regular Expressions For Email, Zip Code and RFC --- .../backbone/install/templates/base_model.coffee | 12 ++++++++++++ .../backbone/install/templates/helpers.coffee | 1 + 2 files changed, 13 insertions(+) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 5f5a23e..5adea7a 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -18,6 +18,18 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model unless (/^\d+\.?\d+$/.test( attrs[key] ) ) (resultMessage[key] ||= []).push(messages.not_a_number) + when "email" + unless ( /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.invalid_email) + + when "rfc" + unless ( /^([A-Z|a-z|&]{3}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)(\w{2})([A-Z|a-z|0-9])$|^([A-Z|a-z]{4}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)((\w{2})([A-Z|a-z|0-9])){0,3}$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.invalid) + + when "zip_code" + unless ( /^\d{5}$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.invalid) + else false ) diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index a0276de..e138b84 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -56,3 +56,4 @@ accepted: "debe ser aceptado" even: "debe ser un número par" odd: "debe ser un número non" + invalid_email: "no es una dirección de correo electrónico válida" From 6da9aafbb1709a9498568e6a3cbc8faa96f77cbc Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 10 Oct 2011 16:40:29 -0500 Subject: [PATCH 29/78] Added support for hasMany in BaseModel --- .../install/templates/base_model.coffee | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 5adea7a..06d2f67 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -1,5 +1,24 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model + initialize: () -> + _.each(@hasMany, + (relation) => + @[relation.key] = new <%= js_app_name %>.Collections[relation.collection] + @[relation.key].url = "#{@[relation.key].url}/#{@id}/#{relation.key}" + @[relation.key].reset @attributes[relation.key] if @attributes[relation.key]? + ) + + toJSON: () -> + json = @attributes + json["#{@paramRoot}_cid"] = "backboneCid_#{@cid}" if @includeCidInJson + _.each(@hasMany, + (relation) => + json["#{relation.key}_attributes"] = @[relation.key].toJSON() if @[relation.key]? + delete json[relation.key] if json[relation.key]? + ) + json + + validates: (attrs, validates = {}) -> resultMessage = {} messages = <%= js_app_name %>.Helpers.errorsMessages @@ -42,3 +61,7 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model isValid: () -> if @validate(@attributes)? then false else true + + includeCidInJson: false + + hasMany: [] From 86bbd34025ae8d318717bdfbf12db646743516b1 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Tue, 11 Oct 2011 13:13:26 -0500 Subject: [PATCH 30/78] Added support to set selected values for inputs (selects and radiobuttons) in backboneLink function --- .../assets/javascripts/backbone_datalink.js | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index 4b1763a..c43c382 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -1,5 +1,15 @@ (function($) { + function setSelectedValueForInput(container, el, value){ + if ( el.is("select") ) + el.find("option[value="+value+"]").attr('selected', true); + + if ( el.is("input:radio") ){ + var radioName = el.attr("name"); + container.find("input[name="+radioName+"][value="+value+"]:radio").attr('checked', true); + } + } + function setValues(el, model){ var attrs = {}; var nestedName = el.attr("name"); @@ -27,10 +37,18 @@ return $.extend($.fn, { backboneLink: function(model) { - $(this).find(":input").each(function() { - var el, name; - el = $(this); - name = el.attr("name"); + var container = $(this); + container.find(":input").each(function() { + var el, name, nestedName, nesteds; + el = $(this); + nestedName = el.attr("name"); + nesteds = nestedName.split("[") + + for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") + name = nesteds[nesteds.length-1]; + + setSelectedValueForInput(container, el, model.get(name)); + model.bind("change:" + name, function() { return el.val(model.get(name)); }); From 46756f33ca9dc2ff414cb09baf76ec1e0abddd76 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Wed, 12 Oct 2011 10:34:43 -0500 Subject: [PATCH 31/78] Fixed bug when set selected values for nesteds inputs (selects and radio buttons) --- .../install/templates/base_model.coffee | 2 +- .../assets/javascripts/backbone_datalink.js | 38 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 06d2f67..3383c5e 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -4,7 +4,7 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model _.each(@hasMany, (relation) => @[relation.key] = new <%= js_app_name %>.Collections[relation.collection] - @[relation.key].url = "#{@[relation.key].url}/#{@id}/#{relation.key}" + @[relation.key].url = "#{@url()}/#{relation.key}" @[relation.key].reset @attributes[relation.key] if @attributes[relation.key]? ) diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index c43c382..447bf1b 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -1,17 +1,6 @@ (function($) { - function setSelectedValueForInput(container, el, value){ - if ( el.is("select") ) - el.find("option[value="+value+"]").attr('selected', true); - - if ( el.is("input:radio") ){ - var radioName = el.attr("name"); - container.find("input[name="+radioName+"][value="+value+"]:radio").attr('checked', true); - } - } - - function setValues(el, model){ - var attrs = {}; + function getNestedObject(el, model){ var nestedName = el.attr("name"); var nesteds = nestedName.split("[") var nestedObject = null; @@ -27,9 +16,28 @@ nestedObject = nestedObject[value]; } else if ( /^backboneCid_.+$/.test(value) ) { value = value.replace("backboneCid_", ""); - nestedObject = nestedObject.getByCid(value) + nestedObject = nestedObject.getByCid(value); } } + return nestedObject; + } + + function setSelectedValueForInput(container, el, model, name){ + var nestedObject = getNestedObject(el, model); + var value = nestedObject.get(name) + if ( el.is("select") ) + el.find("option[value=\""+value+"\"]").attr('selected', true); + + if ( el.is("input:radio") ){ + var radioName = el.attr("name"); + container.find("input[name=\""+radioName+"\"][value=\""+value+"\"]:radio").attr('checked', true); + } + } + + function setValues(el, model, name){ + var attrs = {}; + var nestedObject = getNestedObject(el, model); + attrs[name] = el.val(); nestedObject.set(attrs); return true; @@ -47,14 +55,14 @@ for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") name = nesteds[nesteds.length-1]; - setSelectedValueForInput(container, el, model.get(name)); + setSelectedValueForInput(container, el, model, name); model.bind("change:" + name, function() { return el.val(model.get(name)); }); return $(this).bind("change", function() { el = $(this); - return setValues(el, model); + return setValues(el, model, name); }); }); return $(this); From a71118265689f2dfeef9ef69be77d1c7b069dfdd Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Wed, 12 Oct 2011 12:43:51 -0500 Subject: [PATCH 32/78] Fixed bug in BaseModel initialize function --- lib/generators/backbone/install/templates/base_model.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 3383c5e..d2842f1 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -4,7 +4,7 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model _.each(@hasMany, (relation) => @[relation.key] = new <%= js_app_name %>.Collections[relation.collection] - @[relation.key].url = "#{@url()}/#{relation.key}" + @[relation.key].url = "#{@url()}/#{relation.key}" unless @isNew() @[relation.key].reset @attributes[relation.key] if @attributes[relation.key]? ) From 431311035a92fe71a9f378e5ebc4c7571897d3eb Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 13 Oct 2011 16:30:27 -0500 Subject: [PATCH 33/78] Added support for Human Model Name and Human Attribute Name in Models --- .../install/templates/base_model.coffee | 17 +++++++++++++++++ .../backbone/install/templates/helpers.coffee | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index d2842f1..bb00923 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -65,3 +65,20 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model includeCidInJson: false hasMany: [] + + modelName: () -> + @paramRoot + + humanName: () -> + name = <%= js_app_name %>.Helpers.activerecord.models[@paramRoot] + if name? then name else @paramRoot + + humanAttributeName: (name) -> + modelAttributes = <%= js_app_name %>.Helpers.activerecord.attributes[@paramRoot] + if modelAttributes? + attribute = modelAttributes[name] + attributeName = if attribute? then attribute else name + else + attributeName = name + + attributeName diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index e138b84..ebcf3c6 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -57,3 +57,11 @@ even: "debe ser un número par" odd: "debe ser un número non" invalid_email: "no es una dirección de correo electrónico válida" + + activerecord: + models: + model_name: "Human Model Name" + + attributes: + model_name: + attribute: "Human Attribute Name" From 6d0a5656ede7e47733e4176c20f37d6a61d4df6d Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 13 Oct 2011 18:29:04 -0500 Subject: [PATCH 34/78] Added support for belongsTo in BaseModel --- .../backbone/install/templates/base_model.coffee | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index bb00923..3dabc1e 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -1,11 +1,19 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model initialize: () -> + _.each(@belongsTo, + (relation) => + if relation.key? and @get(relation.foreignKey)? and relation.route? and relation.key? and relation.model? + url = "/#{relation.route}/#{@get(relation.foreignKey)}" + @[relation.key] = new <%= js_app_name %>.Models[relation.model] <%= js_app_name %>.Helpers.jsonData(url) + ) + _.each(@hasMany, (relation) => - @[relation.key] = new <%= js_app_name %>.Collections[relation.collection] - @[relation.key].url = "#{@url()}/#{relation.key}" unless @isNew() - @[relation.key].reset @attributes[relation.key] if @attributes[relation.key]? + if relation.key? and relation.collection? + @[relation.key] = new <%= js_app_name %>.Collections[relation.collection] + @[relation.key].url = "#{@url()}/#{relation.key}" unless @isNew? + @[relation.key].reset @attributes[relation.key] if @attributes[relation.key]? ) toJSON: () -> @@ -66,6 +74,8 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model hasMany: [] + belongsTo: [] + modelName: () -> @paramRoot From a6ca6b8a83b614ad8b834cbbdcfb5b8d6d175a19 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 14 Oct 2011 17:58:25 -0500 Subject: [PATCH 35/78] Added support for BelongsTo in BaseModel --- .../install/templates/base_model.coffee | 59 ++++++++++++++----- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 3dabc1e..c4feaa1 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -1,31 +1,56 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model initialize: () -> - _.each(@belongsTo, - (relation) => - if relation.key? and @get(relation.foreignKey)? and relation.route? and relation.key? and relation.model? - url = "/#{relation.route}/#{@get(relation.foreignKey)}" - @[relation.key] = new <%= js_app_name %>.Models[relation.model] <%= js_app_name %>.Helpers.jsonData(url) + # Callbacks + @bind("afterSave", (model, jqXHR) -> + _.each(@afterSave, (callback, key) -> callback(model, jqXHR) ) ) - _.each(@hasMany, - (relation) => - if relation.key? and relation.collection? - @[relation.key] = new <%= js_app_name %>.Collections[relation.collection] - @[relation.key].url = "#{@url()}/#{relation.key}" unless @isNew? - @[relation.key].reset @attributes[relation.key] if @attributes[relation.key]? + # belongsTo + @setBelongsTo() + _.each(@belongsTo, (relation, key) => @bind("change:#{relation.foreignKey}", () -> @setBelongsTo(key) ) ) + + # hasMany + _.each(@hasMany, (relation, key) => + if relation.collection? + @[key] = new <%= js_app_name %>.Collections[relation.collection] + @[key].url = "#{@url()}/#{key}" unless @isNew() + @[key].reset @attributes[key] if @attributes[key]? ) toJSON: () -> json = @attributes json["#{@paramRoot}_cid"] = "backboneCid_#{@cid}" if @includeCidInJson _.each(@hasMany, - (relation) => - json["#{relation.key}_attributes"] = @[relation.key].toJSON() if @[relation.key]? - delete json[relation.key] if json[relation.key]? + (relation, key) => + json["#{key}_attributes"] = @[key].toJSON() if @[key]? + delete json[key] if json[key]? ) json + prepareToEdit: () -> + @_originalAttributes = _.clone( @toJSON() ) + (window.router._editedModels ||= []).push(@) + + resetToOriginValues: () -> + @set @_originalAttributes + + setBelongsTo: (attribute) -> + if attribute? + relation = @belongsTo[attribute] + if @get(relation.foreignKey) and relation.route? and relation.model? + url = "/#{relation.route}/#{@get(relation.foreignKey)}" + data = <%= js_app_name %>.Helpers.jsonData(url) + if @[attribute]? then @[attribute].set(data) + else @[attribute] = new <%= js_app_name %>.Models[relation.model] data + else + _.each(@belongsTo, (relation, key) => + if @get(relation.foreignKey) and relation.route? and relation.model? + url = "/#{relation.route}/#{@get(relation.foreignKey)}" + data = <%= js_app_name %>.Helpers.jsonData(url) + if @[key]? then @[key].set(data) + else @[key] = new <%= js_app_name %>.Models[relation.model] data + ) validates: (attrs, validates = {}) -> resultMessage = {} @@ -72,9 +97,11 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model includeCidInJson: false - hasMany: [] + hasMany: {} + + belongsTo: {} - belongsTo: [] + afterSave: {} modelName: () -> @paramRoot From a0fee4ebac6cba70bfdb3ead99b48c5f84860b0d Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 14 Oct 2011 18:08:08 -0500 Subject: [PATCH 36/78] Reset models without saving with original values --- .../install/templates/base_view.coffee | 18 ++++++++++++++++-- .../backbone/scaffold/templates/router.coffee | 10 ++++++++++ .../scaffold/templates/views/edit_view.coffee | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index ca9dbb8..0db8aa1 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -29,7 +29,14 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options) - if @model.isValid() then @collection.create(@model, options) + if @model.isValid() + @collection.create(@model, + success: (model, jqXHR) -> + window.router._editedModels = [] + model.trigger("afterSave", model, jqXHR) + options.success(model) + error: options.error + ) else @renderErrors(@model, @model.errors) update : (e, options = {}) -> @@ -48,7 +55,14 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options) - if @model.isValid() then @model.save(null, options) + if @model.isValid() + @model.save(null, + success: (model, jqXHR) -> + window.router._editedModels = [] + model.trigger("afterSave", model, jqXHR) + options.success(model) + error: options.error + ) else @renderErrors(@model, @model.errors) renderErrors: (model, errors) -> diff --git a/lib/generators/backbone/scaffold/templates/router.coffee b/lib/generators/backbone/scaffold/templates/router.coffee index 8f06e10..5bb56ca 100644 --- a/lib/generators/backbone/scaffold/templates/router.coffee +++ b/lib/generators/backbone/scaffold/templates/router.coffee @@ -11,23 +11,33 @@ class <%= router_namespace %>Router extends Backbone.Router ".*" : "index" new<%= class_name %>: -> + @resetModelsWithoutSaving() @new_view = new <%= "#{view_namespace}.NewView(collection: @#{plural_model_name})" %> $("#<%= plural_name %>").html(@new_view.render().el) index: -> + @resetModelsWithoutSaving() @index_view.remove() if @index_view? @index_view = new <%= "#{view_namespace}.IndexView(#{plural_model_name}: @#{plural_model_name})" %> $("#<%= plural_name %>").html(@index_view.render().el) show: (id) -> + @resetModelsWithoutSaving() <%= singular_name %> = @<%= plural_model_name %>.get(id) @show_view = new <%= "#{view_namespace}.ShowView(model: #{singular_name})" %> $("#<%= plural_name %>").html(@show_view.render().el) edit: (id) -> + @resetModelsWithoutSaving() <%= singular_name %> = @<%= plural_model_name %>.get(id) @edit_view.remove() if @edit_view? @edit_view = new <%= "#{view_namespace}.EditView(model: #{singular_name})" %> $("#<%= plural_name %>").html(@edit_view.render().el) + + resetModelsWithoutSaving: () -> + _.each(@_editedModels, (model) -> + model.resetToOriginValues() + ) + @_editedModels = [] diff --git a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee index d01348d..43d85c1 100644 --- a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee @@ -5,6 +5,7 @@ class <%= view_namespace %>.EditView extends <%= js_app_name %>.Views.BaseView initialize: -> @model.bind("error", @renderErrors) + @model.prepareToEdit() events: _.extend( _.clone(@__super__.events), From 898dbe8c6d71f718dfa98db7bc98ec5b5e4bba54 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 17 Oct 2011 12:53:53 -0500 Subject: [PATCH 37/78] Added toUnderscore and toCamelize methods in Helpers File --- .../backbone/install/templates/helpers.coffee | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index ebcf3c6..8b368ab 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -65,3 +65,20 @@ attributes: model_name: attribute: "Human Attribute Name" + + +# Strings +String.prototype.toUnderscore = () -> + @replace( /([A-Z])/g, ($1) -> "_"+$1.toLowerCase() ). + replace( /^_/, '' ) + +String.prototype.toCamelize = (type) -> + value = @replace(/(_| )/, "-"). + replace(/(\-[a-z])/g, ($1) -> $1.toUpperCase().replace('-','') ). + replace( /^([a-z])/g, ($1) -> $1.toUpperCase() ) + + switch type + when "lower" then value = value.replace( /^([A-Z])/g, ($1) -> $1.toLowerCase() ) + else value + + value From 8cedb889d69d40a7e6d47b5e0115aaa6dd21f811 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Tue, 18 Oct 2011 09:59:36 -0500 Subject: [PATCH 38/78] jqXHR is passed to success callback in methods for save and update (BaseView) --- lib/generators/backbone/install/templates/base_view.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index 0db8aa1..046e358 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -34,7 +34,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View success: (model, jqXHR) -> window.router._editedModels = [] model.trigger("afterSave", model, jqXHR) - options.success(model) + options.success(model, jqXHR) error: options.error ) else @renderErrors(@model, @model.errors) @@ -60,7 +60,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View success: (model, jqXHR) -> window.router._editedModels = [] model.trigger("afterSave", model, jqXHR) - options.success(model) + options.success(model, jqXHR) error: options.error ) else @renderErrors(@model, @model.errors) From f700bef03689262436ccb79edc8fd7bb7dcd2fcc Mon Sep 17 00:00:00 2001 From: ignoch Date: Thu, 20 Oct 2011 17:32:32 -0500 Subject: [PATCH 39/78] added minor changes in scaffold templates --- .../backbone/scaffold/templates/templates/edit.haml | 9 +++------ .../backbone/scaffold/templates/templates/index.haml | 8 +++----- .../backbone/scaffold/templates/templates/new.haml | 9 +++------ .../backbone/scaffold/templates/templates/show.haml | 11 ++++------- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/lib/generators/backbone/scaffold/templates/templates/edit.haml b/lib/generators/backbone/scaffold/templates/templates/edit.haml index b5d3488..4ba791a 100644 --- a/lib/generators/backbone/scaffold/templates/templates/edit.haml +++ b/lib/generators/backbone/scaffold/templates/templates/edit.haml @@ -4,11 +4,8 @@ %h1 = t(".title") ${<%= attributes.first.try(:name) %>} - -.row - .span16.columns - %ul.tabs - %li - = link_to t("links.back"), "#/index" + %ul.tabs + %li + = link_to t("links.back"), "#/index" = render :partial => "form", :locals => { :form_type => "edit" } diff --git a/lib/generators/backbone/scaffold/templates/templates/index.haml b/lib/generators/backbone/scaffold/templates/templates/index.haml index ca45d10..48c1dfe 100644 --- a/lib/generators/backbone/scaffold/templates/templates/index.haml +++ b/lib/generators/backbone/scaffold/templates/templates/index.haml @@ -2,11 +2,9 @@ .span16.columns .page-header %h1= t(".title") -.row - .span16.columns - %ul.tabs - %li - = link_to t("links.new", :resource => <%= classify_model_name %>.model_name.human), "#/new" + %ul.tabs + %li + = link_to t("links.new", :resource => <%= classify_model_name %>.model_name.human), "#/new" .row .span16.columns diff --git a/lib/generators/backbone/scaffold/templates/templates/new.haml b/lib/generators/backbone/scaffold/templates/templates/new.haml index 9f80eb3..ddc27ed 100644 --- a/lib/generators/backbone/scaffold/templates/templates/new.haml +++ b/lib/generators/backbone/scaffold/templates/templates/new.haml @@ -2,11 +2,8 @@ .span16.columns .page-header %h1= t(".title") - -.row - .span16.columns - %ul.tabs - %li - = link_to t("links.back"), "#/index" + %ul.tabs + %li + = link_to t("links.back"), "#/index" = render :partial => "form", :locals => { :form_type => "new" } diff --git a/lib/generators/backbone/scaffold/templates/templates/show.haml b/lib/generators/backbone/scaffold/templates/templates/show.haml index 5d07841..8abd3b6 100644 --- a/lib/generators/backbone/scaffold/templates/templates/show.haml +++ b/lib/generators/backbone/scaffold/templates/templates/show.haml @@ -2,13 +2,10 @@ .span16.columns .page-header %h1= t(".title") - -.row - .span16.columns - %ul.tabs - %li= link_to t("links.back"), "#/index" - %li= link_to t("links.edit"), "#/${id}/edit" - %li= link_to t("links.destroy"), "#/index", :class => "destroy", :confirm => t("links.confirm") + %ul.tabs + %li= link_to t("links.back"), "#/index" + %li= link_to t("links.edit"), "#/${id}/edit" + %li= link_to t("links.destroy"), "#/index", :class => "destroy", :confirm => t("links.confirm") .row .span10.columns From 2959f6649bee8ff117395c1f1807d92a7c08b732 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 21 Oct 2011 13:04:56 -0500 Subject: [PATCH 40/78] Added support for pagination --- .../backbone/install/install_generator.rb | 4 ++ .../install/templates/alerts/_pagination.haml | 26 ++++++++++++ .../install/templates/base_model.coffee | 9 +++- .../install/templates/base_view.coffee | 41 +++++++++++++++++++ .../backbone/scaffold/templates/router.coffee | 6 ++- .../scaffold/templates/templates/index.haml | 2 + .../templates/templates/pagination.haml | 18 -------- .../templates/views/index_view.coffee | 7 +++- 8 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 lib/generators/backbone/install/templates/alerts/_pagination.haml delete mode 100644 lib/generators/backbone/scaffold/templates/templates/pagination.haml diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index bdcb0e9..991a78d 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -75,6 +75,10 @@ def create_dir_backbone_alerts template "alerts/_warning_alert.haml", "app/views/backbone_alerts/_warning_alert.html.haml" end + def create_pagination_template + template "alerts/_pagination.haml", "app/views/backbone_alerts/_pagination.html.haml" + end + end end end diff --git a/lib/generators/backbone/install/templates/alerts/_pagination.haml b/lib/generators/backbone/install/templates/alerts/_pagination.haml new file mode 100644 index 0000000..07b6978 --- /dev/null +++ b/lib/generators/backbone/install/templates/alerts/_pagination.haml @@ -0,0 +1,26 @@ +.row + %hr + .pagination + %ul + + {{if paginatePrev}} + %li.prev + = link_to t('will_paginate.previous'), '${resources_path}?page=${paginatePrev}' + {{else}} + %li.prev.disabled + = link_to t('will_paginate.previous'), '#' + {{/if}} + + {{each pages}} + %li{:class => "${liKlass}"} + = link_to "${text}", '${path}' + {{/each}} + + {{if paginateNext}} + %li.next + = link_to t('will_paginate.next'), '${resources_path}?page=${paginateNext}' + {{else}} + %li.next.disabled + = link_to t('will_paginate.next'), '#' + {{/if}} + diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index c4feaa1..d3342bc 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -29,8 +29,11 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model json prepareToEdit: () -> - @_originalAttributes = _.clone( @toJSON() ) - (window.router._editedModels ||= []).push(@) + window.router._editedModels ||= [] + index = _.indexOf(window.router._editedModels, @) + if index is -1 + @_originalAttributes = _.clone( @toJSON() ) + window.router._editedModels.push(@) resetToOriginValues: () -> @set @_originalAttributes @@ -97,10 +100,12 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model includeCidInJson: false + # Relations hasMany: {} belongsTo: {} + # Callbacks afterSave: {} modelName: () -> diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index 046e358..efc83f2 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -3,6 +3,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View # Defaults Events events: "click .destroy" : "destroy" + "click div.pagination a" : "pagination" destroy: (e, options = {}) -> msg = $(e.currentTarget).attr("data-confirm") @@ -65,6 +66,8 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View ) else @renderErrors(@model, @model.errors) + # Errors + # ________________________________________________________________________ renderErrors: (model, errors) -> fullErrors = {} _.each(errors, (messages, key) -> @@ -73,3 +76,41 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View (fullErrors.errors ||= []).push({name: name, message: message}) ) <%= js_app_name %>.Helpers.renderErrors(fullErrors) + + # Pagination + # ________________________________________________________________________ + pagination: (e, collection) -> + e.preventDefault() + link = $(e.currentTarget) + li = link.closest("li") + + unless li.is(".active, .prev.disabled, .next.disabled") + href = link.attr("href") + data = <%= js_app_name %>.Helpers.jsonData href + collection.pagination = data.pagination + collection.reset data.resources + + renderPagination: (collection) -> + pagination = collection.pagination || {} + + if pagination.total_pages > 1 + pagination.resources_path = collection.url + pagination.pages = [] + + if (pagination.current_page > 1) + pagination.paginatePrev = (pagination.current_page - 1) + + if (pagination.current_page < pagination.total_pages) + pagination.paginateNext = (pagination.current_page + 1) + + # builder pages + for number in [1..pagination.total_pages] + page = {} + page.liKlass = "active" if pagination.current_page is number + page.text = number + page.path = "#{pagination.resources_path}?page=#{number}" + pagination.pages.push(page) + + @$("#pagination-container").html( + $("#backboneTemplatesPagination").tmpl(pagination) + ) diff --git a/lib/generators/backbone/scaffold/templates/router.coffee b/lib/generators/backbone/scaffold/templates/router.coffee index 5bb56ca..d6194f0 100644 --- a/lib/generators/backbone/scaffold/templates/router.coffee +++ b/lib/generators/backbone/scaffold/templates/router.coffee @@ -1,7 +1,11 @@ class <%= router_namespace %>Router extends Backbone.Router initialize: (options) -> @<%= plural_model_name %> = new <%= collection_namespace %>Collection() - @<%= plural_model_name %>.reset options.<%= plural_model_name %> + + if options.<%= plural_model_name %>.pagination? + @<%= plural_model_name %>.reset options.<%= plural_model_name %>.resources + @<%= plural_model_name %>.pagination = options.<%= plural_model_name %>.pagination + else @<%= plural_model_name %>.reset options.<%= plural_model_name %> routes: "/new" : "new<%= class_name %>" diff --git a/lib/generators/backbone/scaffold/templates/templates/index.haml b/lib/generators/backbone/scaffold/templates/templates/index.haml index 48c1dfe..74476bd 100644 --- a/lib/generators/backbone/scaffold/templates/templates/index.haml +++ b/lib/generators/backbone/scaffold/templates/templates/index.haml @@ -16,3 +16,5 @@ <% end -%> %th %tbody + +#pagination-container diff --git a/lib/generators/backbone/scaffold/templates/templates/pagination.haml b/lib/generators/backbone/scaffold/templates/templates/pagination.haml deleted file mode 100644 index d4d950f..0000000 --- a/lib/generators/backbone/scaffold/templates/templates/pagination.haml +++ /dev/null @@ -1,18 +0,0 @@ -.row - %hr - .pagination - %ul - %li.prev.disabled - %a{:href => "#"} ← Previous - %li.active - %a{:href => "#"} 1 - %li - %a{:href => "#"} 2 - %li - %a{:href => "#"} 3 - %li - %a{:href => "#"} 4 - %li - %a{:href => "#"} 5 - %li.next - %a{:href => "#"} → Previous diff --git a/lib/generators/backbone/scaffold/templates/views/index_view.coffee b/lib/generators/backbone/scaffold/templates/views/index_view.coffee index 814f429..d1c5dc6 100644 --- a/lib/generators/backbone/scaffold/templates/views/index_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/index_view.coffee @@ -13,11 +13,13 @@ class <%= view_namespace %>.IndexView extends <%= js_app_name %>.Views.BaseView ) addAll: () -> + @$("#<%= plural_name %>-table tbody").empty() + @renderPagination(@options.<%= plural_model_name %>) if @options.<%= plural_model_name %>.pagination? @options.<%= plural_model_name %>.each(@addOne) addOne: (<%= singular_model_name %>) -> view = new <%= view_namespace %>.<%= singular_name.camelize %>View({model : <%= singular_model_name %>}) - @$("tbody").append(view.render().el) + @$("#<%= plural_name %>-table tbody").append(view.render().el) render: -> $(@el).html(@template(<%= plural_model_name %>: @options.<%= plural_model_name %>.toJSON() )) @@ -28,3 +30,6 @@ class <%= view_namespace %>.IndexView extends <%= js_app_name %>.Views.BaseView remove: -> @options.<%= plural_model_name %>.unbind('reset', @addAll) super() + + pagination: (e) -> + super(e, @options.<%= plural_model_name %>) From e9336937ef185663c272b49112c5e8da23b74123 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 21 Oct 2011 13:43:40 -0500 Subject: [PATCH 41/78] Added BackboneResponses with support for acts_as_api gem --- .../backbone/install/install_generator.rb | 4 + .../install/templates/backbone_responses.rb | 118 ++++++++++++++++++ .../backbone/scaffold/templates/controller.rb | 2 + 3 files changed, 124 insertions(+) create mode 100644 lib/generators/backbone/install/templates/backbone_responses.rb diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 991a78d..69ca6cd 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -79,6 +79,10 @@ def create_pagination_template template "alerts/_pagination.haml", "app/views/backbone_alerts/_pagination.html.haml" end + def create_backbone_responses + template "backbone_responses.rb", "lib/backbone_responses.rb" + end + end end end diff --git a/lib/generators/backbone/install/templates/backbone_responses.rb b/lib/generators/backbone/install/templates/backbone_responses.rb new file mode 100644 index 0000000..63c2277 --- /dev/null +++ b/lib/generators/backbone/install/templates/backbone_responses.rb @@ -0,0 +1,118 @@ +module BackboneResponses + + def self.included(base) + base.send :include, InstanceMethods + base.send :extend, ClassMethods + end + + module ClassMethods + # Add class methods here + end + + module InstanceMethods + # Add instance methods here + + def index + collection_public_attributes + + respond_to do |format| + format.html + format.json { + render :json => instance_variable_get("@#{controller_name}") + } + end + end + + def update + update! do |format| + format.json do + render :json => resource_public_attributes + end + end + end + + def create + create! do |format| + format.json do + render :json => resource_public_attributes + end + end + end + + def show + respond_to do |format| + format.json do + render :json => resource_public_attributes + end + end + end + + protected + + def collection + if paginate? + resources = end_of_association_chain.paginate( + :page => (params[:page] || 1), :per_page => resources_per_page) + else + resources = end_of_association_chain.all + end + instance_variable_set("@#{controller_name}" , resources) + end + + def resource_public_attributes + model = controller_name.classify.constantize + if model.respond_to?(:acts_as_api?) and model.acts_as_api? and model.respond_to?(:"api_accessible_#{api_resource_template}") + resource.as_api_response(:"#{api_resource_template}") + else + resource + end + end + + def collection_public_attributes + model = controller_name.classify.constantize + resources = collection + + if model.respond_to?(:acts_as_api?) and model.acts_as_api? and model.respond_to?(:"api_accessible_#{api_collection_template}") + allowed_keys = resources.collect{|o| o.as_api_response(:"#{api_collection_template}")} + else + allowed_keys = resources + end + + if paginate? + per_page = resources.per_page + total_entries = resources.total_entries + total_pages = (total_entries.to_f / per_page.to_f).ceil + + resources_with_pagination = {} + resources_with_pagination[:resources] = allowed_keys + resources_with_pagination[:pagination] = { + :current_page => resources.current_page, + :per_page => per_page, + :total_entries => total_entries, + :total_pages => total_pages + } + instance_variable_set("@#{controller_name}" , resources_with_pagination) + else + instance_variable_set("@#{controller_name}" , allowed_keys) + end + end + + end + + def api_collection_template + "public" + end + + def api_resource_template + "public" + end + + def paginate? + true + end + + def resources_per_page + 50 + end + +end diff --git a/lib/generators/backbone/scaffold/templates/controller.rb b/lib/generators/backbone/scaffold/templates/controller.rb index 5da6292..a3dbb43 100644 --- a/lib/generators/backbone/scaffold/templates/controller.rb +++ b/lib/generators/backbone/scaffold/templates/controller.rb @@ -1,4 +1,6 @@ class <%= plural_name.camelize %>Controller < InheritedResources::Base + include BackboneResponses + respond_to :json end From d29a63c700d41929574af036ecccd92c06aa12cc Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Wed, 2 Nov 2011 09:57:15 -0600 Subject: [PATCH 42/78] Fixed bug in BackboneResponses --- .../backbone/install/templates/backbone_responses.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/generators/backbone/install/templates/backbone_responses.rb b/lib/generators/backbone/install/templates/backbone_responses.rb index 63c2277..34899ad 100644 --- a/lib/generators/backbone/install/templates/backbone_responses.rb +++ b/lib/generators/backbone/install/templates/backbone_responses.rb @@ -60,11 +60,13 @@ def collection end def resource_public_attributes - model = controller_name.classify.constantize + model = end_of_association_chain + object = reload_resource ? resource.reload : resource + if model.respond_to?(:acts_as_api?) and model.acts_as_api? and model.respond_to?(:"api_accessible_#{api_resource_template}") - resource.as_api_response(:"#{api_resource_template}") + object.as_api_response(:"#{api_resource_template}") else - resource + object end end @@ -115,4 +117,8 @@ def resources_per_page 50 end + def reload_resource + false + end + end From 346fa7a0e5d5f54bd2e696137b8bf1563055a1ea Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Wed, 2 Nov 2011 13:51:38 -0600 Subject: [PATCH 43/78] Added CollectionBase && Added suport in BaseModel for delegates && Improvements in hasMany and belongsTo relations and toJSON in BaseModel --- .../backbone/install/install_generator.rb | 4 + .../templates/alerts/_error_alert.haml | 2 +- .../backbone/install/templates/app.coffee | 1 + .../install/templates/base_collection.coffee | 6 + .../install/templates/base_model.coffee | 179 +++++++++++++++--- .../install/templates/base_view.coffee | 10 +- .../backbone/install/templates/helpers.coffee | 5 +- .../backbone/model/templates/model.coffee | 8 +- .../backbone/scaffold/templates/model.coffee | 5 +- .../scaffold/templates/views/edit_view.coffee | 2 +- .../templates/views/index_view.coffee | 2 +- .../templates/views/model_view.coffee | 2 +- .../scaffold/templates/views/new_view.coffee | 2 +- .../scaffold/templates/views/show_view.coffee | 2 +- 14 files changed, 190 insertions(+), 40 deletions(-) create mode 100644 lib/generators/backbone/install/templates/base_collection.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 69ca6cd..da4c5d6 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -67,6 +67,10 @@ def create_base_view_file template "base_view.coffee", "app/assets/javascripts/backbone/views/base_view.js.coffee" end + def create_base_collection_file + template "base_collection.coffee", "app/assets/javascripts/backbone/models/base_collection.js.coffee" + end + def create_dir_backbone_alerts empty_directory "app/views/backbone_alerts" template "alerts/_error_alert.haml", "app/views/backbone_alerts/_error_alert.html.haml" diff --git a/lib/generators/backbone/install/templates/alerts/_error_alert.haml b/lib/generators/backbone/install/templates/alerts/_error_alert.haml index cb9952c..9b1f6dd 100644 --- a/lib/generators/backbone/install/templates/alerts/_error_alert.haml +++ b/lib/generators/backbone/install/templates/alerts/_error_alert.haml @@ -1,4 +1,4 @@ -.alert-message.error +.alert-message.error.block-message %a.close{:href =>"#"} x {{each errors}} diff --git a/lib/generators/backbone/install/templates/app.coffee b/lib/generators/backbone/install/templates/app.coffee index f73b57c..2d1b479 100644 --- a/lib/generators/backbone/install/templates/app.coffee +++ b/lib/generators/backbone/install/templates/app.coffee @@ -1,6 +1,7 @@ #= require_self #= require ./helpers #= require ./models/base_model +#= require ./models/base_collection #= require_tree ./models #= require ./views/base_view #= require_tree ./views diff --git a/lib/generators/backbone/install/templates/base_collection.coffee b/lib/generators/backbone/install/templates/base_collection.coffee new file mode 100644 index 0000000..a72e985 --- /dev/null +++ b/lib/generators/backbone/install/templates/base_collection.coffee @@ -0,0 +1,6 @@ +class <%= js_app_name %>.Collections.BaseCollection extends Backbone.Collection + + # The JSON representation of a Collection is an array of the + # models' attributes. + toJSON: ( includeRelations = false ) -> + @map( (model) -> model.toJSON(includeRelations) ) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index d3342bc..0712261 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -1,31 +1,87 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model - initialize: () -> + initialize: (attributes, options) -> + # Clone de original attributes + attributes = _.extend({}, _.clone(attributes)) + # Callbacks @bind("afterSave", (model, jqXHR) -> - _.each(@afterSave, (callback, key) -> callback(model, jqXHR) ) + _.each(@afterSave, (callback, key) -> callback?(model, jqXHR) ) ) # belongsTo - @setBelongsTo() - _.each(@belongsTo, (relation, key) => @bind("change:#{relation.foreignKey}", () -> @setBelongsTo(key) ) ) + @setBelongsTo(attributes, null) + _.each(@belongsTo, (relation, key) => + relation = @buildBelonsToRelation(relation, key) + @bind("change:#{relation.foreignKey}", () -> + @setBelongsTo({}, key) + ) + ) # hasMany _.each(@hasMany, (relation, key) => if relation.collection? - @[key] = new <%= js_app_name %>.Collections[relation.collection] - @[key].url = "#{@url()}/#{key}" unless @isNew() - @[key].reset @attributes[key] if @attributes[key]? + # Create a new collection object if not exist + unless @[key]? + @[key] = new <%= js_app_name %>.Collections[relation.collection] + @[key].url = "#{@collectionRoute}/#{attributes.id}/#{key}" unless @isNew() + + @[key].reset attributes[key] if attributes[key]? ) - toJSON: () -> - json = @attributes - json["#{@paramRoot}_cid"] = "backboneCid_#{@cid}" if @includeCidInJson + # Call After Initialize Callback + @afterInitialize() + + toJSON: ( includeRelations = false ) -> + json = _.clone @attributes + + if includeRelations is true + json["#{@paramRoot}_cid"] = "backboneCid_#{@cid}" + + # belongsTo + _.each(@belongsTo, + (relation, key) => + relation = @buildBelonsToRelation(relation, key) + + # include nesteds attributes for save with AJAX + if includeRelations is false + if @[key]? and relation.isNested is true + if relation.isPolymorphic isnt true + json["#{key}_attributes"] = @[key].toJSON(includeRelations) + delete json[key] + + # include all values to use in Show view for example + else if @[key]? + json[key] = @[key].toJSON(includeRelations) + + # include delegates + delegate = @delegates[key] || {} + _.each(delegate.attributes, (name) -> + if delegate.prefix is true then keyName = "#{key}_#{name}" + else keyName = name + json[keyName] = json[key][name] + ) + + ) + # hasMany _.each(@hasMany, (relation, key) => - json["#{key}_attributes"] = @[key].toJSON() if @[key]? - delete json[key] if json[key]? + if includeRelations is false + if @[key]? and relation.isNested is true + json["#{key}_attributes"] = @[key].toJSON(includeRelations) + delete json[key] + else if @[key]? + json[key] = @[key].toJSON(includeRelations) ) + + # Attributes that are eliminated are not part of the model + # only used to display information with some custom format + if includeRelations is false + _.each(@removeWhenSaving, (value) -> + delete json[value] + ) + + json prepareToEdit: () -> @@ -38,23 +94,90 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model resetToOriginValues: () -> @set @_originalAttributes - setBelongsTo: (attribute) -> - if attribute? - relation = @belongsTo[attribute] - if @get(relation.foreignKey) and relation.route? and relation.model? - url = "/#{relation.route}/#{@get(relation.foreignKey)}" - data = <%= js_app_name %>.Helpers.jsonData(url) - if @[attribute]? then @[attribute].set(data) - else @[attribute] = new <%= js_app_name %>.Models[relation.model] data + setBelongsTo: (attributes, callbackKey) -> + # For reload association object when foreignKey has changed + if callbackKey? + relation = @belongsTo[callbackKey] + @createBelongsToRelation(attributes, relation, callbackKey, callbackKey) + + # For load association when and models is instantiated else _.each(@belongsTo, (relation, key) => - if @get(relation.foreignKey) and relation.route? and relation.model? - url = "/#{relation.route}/#{@get(relation.foreignKey)}" - data = <%= js_app_name %>.Helpers.jsonData(url) - if @[key]? then @[key].set(data) - else @[key] = new <%= js_app_name %>.Models[relation.model] data + @createBelongsToRelation(attributes, relation, key, callbackKey) ) + createBelongsToRelation: (attributes, relation, key, callbackKey) -> + relation = @buildBelonsToRelation(relation, key) + + if relation.model? + + unless @[key]? + @[key] = new <%= js_app_name %>.Models[relation.model] attributes[key] + + # Retrieve values from database if foreignKey has changed + else if callbackKey? and relation.isNested isnt true + if newValue = @get(relation.foreignKey) + if newValue isnt @[key].get("id") + url = "/#{relation.route}/#{newValue}" + data = <%= js_app_name %>.Helpers.jsonData(url) + + # Set values in association model + @[key].set(data) if data? + + # clear attributes if foreignKey is null + else @[key].clear silent: true + + else + # Create a new Backbone Model for use toJSON function + @[key] = new Backbone.Model + + buildBelonsToRelation: (relation, key) -> + relation = _.clone relation + + # When belongsTo is a polymorphic association + if relation.isPolymorphic is true + relation = @polymorphicRelation(relation, key) + + else + # If route is not defined it's taken from model collectionRoute + unless relation.route? + relation.route = <%= js_app_name %>.Models[relation.model].collectionRoute + + # If foreignKey is not defined it's taken from model paramRoot more "_id" + unless relation.foreignKey? + relation.foreignKey = "#{<%= js_app_name %>.Models[relation.model].paramRoot}_id" + + relation + + + polymorphicRelation: (relation, key) -> + polymorphicType = "#{key}_type" + relation.foreignKey = "#{key}_id" + + if (modelName = @get(polymorphicType))? + relation.route = <%= js_app_name %>.Models[modelName].collectionRoute + relation.model = modelName + + relation + + resetRelations: (attributes) -> + # belongsTo + _.each(@belongsTo, + (relation, key) => + values = attributes[key] + relation = @buildBelonsToRelation(relation, key) + if values? and relation.isNested is true + @[key] = new <%= js_app_name %>.Models[relation.model] values + ) + # hasMany + _.each(@hasMany, + (relation, key) => + values = attributes[key] + @[key].url = "#{@collectionRoute}/#{@get('id')}/#{key}" unless @isNew() + @[key].reset values if values? + ) + + validates: (attrs, validates = {}) -> resultMessage = {} messages = <%= js_app_name %>.Helpers.errorsMessages @@ -105,9 +228,15 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model belongsTo: {} + delegates: {} + + removeWhenSaving: [] + # Callbacks afterSave: {} + afterInitialize: () -> + modelName: () -> @paramRoot diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index efc83f2..fcae101 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -23,7 +23,6 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options = _.extend( success: (model) => - @model = model window.location.hash = "/#{@model.id}" error: (model, jqXHR) => @renderErrors( model, $.parseJSON( jqXHR.responseText ) ) @@ -32,15 +31,16 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View if @model.isValid() @collection.create(@model, - success: (model, jqXHR) -> + success: (model, jqXHR) => window.router._editedModels = [] + @model.resetRelations(jqXHR) model.trigger("afterSave", model, jqXHR) options.success(model, jqXHR) error: options.error ) else @renderErrors(@model, @model.errors) - update : (e, options = {}) -> + update: (e, options = {}) -> e.preventDefault() e.stopPropagation() @@ -49,7 +49,6 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options = _.extend( success : (model) => - @model = model window.location.hash = "/#{@model.id}" error: (model, jqXHR) => @renderErrors( model, $.parseJSON( jqXHR.responseText ) ) @@ -58,8 +57,9 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View if @model.isValid() @model.save(null, - success: (model, jqXHR) -> + success: (model, jqXHR) => window.router._editedModels = [] + @model.resetRelations(jqXHR) model.trigger("afterSave", model, jqXHR) options.success(model, jqXHR) error: options.error diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index 8b368ab..bb84543 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -20,7 +20,10 @@ $("#alerts_container").html( $("#backboneWarningAlert").tmpl(data) ) renderErrors: (data) -> - $("#alerts_container").html( $("#backboneErrorAlert").tmpl(data) ) + $('.alert-message').remove() + container = $(".columns form:first") + container.prepend( $("#backboneErrorAlert").tmpl(data) ) + $('html, body').animate({ scrollTop: container.offset().top - 45 }, 'slow') renderSuccess: (data) -> $("#alerts_container").html( $("#backboneSuccessAlert").tmpl(data) ) diff --git a/lib/generators/backbone/model/templates/model.coffee b/lib/generators/backbone/model/templates/model.coffee index c763032..9e977c9 100644 --- a/lib/generators/backbone/model/templates/model.coffee +++ b/lib/generators/backbone/model/templates/model.coffee @@ -1,5 +1,6 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel - paramRoot: '<%= singular_table_name %>' + paramRoot: '<%= singular_name %>' + collectionRoute: '<%= plural_name %>' defaults: <% attributes.each do |attribute| -%> @@ -11,7 +12,10 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel # example: : "presence" }) +<%= model_namespace %>.paramRoot = '<%= singular_name %>' +<%= model_namespace %>.collectionRoute = '<%= plural_name %>' -class <%= collection_namespace %>Collection extends Backbone.Collection +class <%= collection_namespace %>Collection extends <%= js_app_name %>.Collections.BaseCollection model: <%= model_namespace %> url: '<%= route_url %>' + diff --git a/lib/generators/backbone/scaffold/templates/model.coffee b/lib/generators/backbone/scaffold/templates/model.coffee index fe0be31..052f153 100644 --- a/lib/generators/backbone/scaffold/templates/model.coffee +++ b/lib/generators/backbone/scaffold/templates/model.coffee @@ -1,5 +1,6 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel paramRoot: '<%= singular_name %>' + collectionRoute: '<%= plural_name %>' defaults: <% attributes.each do |attribute| -%> @@ -11,7 +12,9 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel # example: : "presence" }) +<%= model_namespace %>.paramRoot = '<%= singular_name %>' +<%= model_namespace %>.collectionRoute = '<%= plural_name %>' -class <%= collection_namespace %>Collection extends Backbone.Collection +class <%= collection_namespace %>Collection extends <%= js_app_name %>.Collections.BaseCollection model: <%= model_namespace %> url: '<%= route_url %>' diff --git a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee index 43d85c1..19b3746 100644 --- a/lib/generators/backbone/scaffold/templates/views/edit_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/edit_view.coffee @@ -13,7 +13,7 @@ class <%= view_namespace %>.EditView extends <%= js_app_name %>.Views.BaseView ) render: -> - $(@el).html( @template( @model.toJSON() ) ) + $(@el).html( @template( @model.toJSON(true) ) ) this.$("form#edit_<%= singular_name %>").backboneLink(@model) return this diff --git a/lib/generators/backbone/scaffold/templates/views/index_view.coffee b/lib/generators/backbone/scaffold/templates/views/index_view.coffee index d1c5dc6..54f78d3 100644 --- a/lib/generators/backbone/scaffold/templates/views/index_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/index_view.coffee @@ -22,7 +22,7 @@ class <%= view_namespace %>.IndexView extends <%= js_app_name %>.Views.BaseView @$("#<%= plural_name %>-table tbody").append(view.render().el) render: -> - $(@el).html(@template(<%= plural_model_name %>: @options.<%= plural_model_name %>.toJSON() )) + $(@el).html(@template(<%= plural_model_name %>: @options.<%= plural_model_name %>.toJSON(true) )) @addAll() return this diff --git a/lib/generators/backbone/scaffold/templates/views/model_view.coffee b/lib/generators/backbone/scaffold/templates/views/model_view.coffee index bfc36a3..15d65e5 100644 --- a/lib/generators/backbone/scaffold/templates/views/model_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/model_view.coffee @@ -11,5 +11,5 @@ class <%= view_namespace %>.<%= singular_name.camelize %>View extends <%= js_app ) render: -> - $(@el).html( @template( @model.toJSON() ) ) + $(@el).html( @template( @model.toJSON(true) ) ) return this diff --git a/lib/generators/backbone/scaffold/templates/views/new_view.coffee b/lib/generators/backbone/scaffold/templates/views/new_view.coffee index 42edb31..b3093da 100644 --- a/lib/generators/backbone/scaffold/templates/views/new_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/new_view.coffee @@ -14,6 +14,6 @@ class <%= view_namespace %>.NewView extends <%= js_app_name %>.Views.BaseView ) render: -> - $(@el).html( @template( @model.toJSON() ) ) + $(@el).html( @template( @model.toJSON(true) ) ) this.$("form#new_<%= singular_name %>").backboneLink(@model) return this diff --git a/lib/generators/backbone/scaffold/templates/views/show_view.coffee b/lib/generators/backbone/scaffold/templates/views/show_view.coffee index 8530ac6..227d460 100644 --- a/lib/generators/backbone/scaffold/templates/views/show_view.coffee +++ b/lib/generators/backbone/scaffold/templates/views/show_view.coffee @@ -9,7 +9,7 @@ class <%= view_namespace %>.ShowView extends <%= js_app_name %>.Views.BaseView ) render: -> - $(@el).html( @template( @model.toJSON() ) ) + $(@el).html( @template( @model.toJSON(true) ) ) return this destroy: (e) -> From cf2b572bbc87bf24794a4aa6ba80e184ee58d0b2 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 3 Nov 2011 13:59:28 -0600 Subject: [PATCH 44/78] Fixed bug in backbone_datalink.js --- vendor/assets/javascripts/backbone_datalink.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index 447bf1b..5a306d7 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -47,18 +47,19 @@ backboneLink: function(model) { var container = $(this); container.find(":input").each(function() { - var el, name, nestedName, nesteds; - el = $(this); - nestedName = el.attr("name"); - nesteds = nestedName.split("[") + var el, name, nestedName, nesteds, nestedObject; + el = $(this); + nestedName = el.attr("name"); + nesteds = nestedName.split("[") + nestedObject = getNestedObject(el, model); for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") name = nesteds[nesteds.length-1]; setSelectedValueForInput(container, el, model, name); - model.bind("change:" + name, function() { - return el.val(model.get(name)); + nestedObject.bind("change:" + name, function() { + return el.val(nestedObject.get(name)); }); return $(this).bind("change", function() { el = $(this); From be5c601dd14c6a314efb7b419f5258538481a25d Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Fri, 4 Nov 2011 11:16:20 -0600 Subject: [PATCH 45/78] Added equalTo validation in BaseModel --- .../install/templates/base_model.coffee | 54 ++++++++++++------- .../backbone/install/templates/helpers.coffee | 2 +- .../assets/javascripts/backbone_datalink.js | 5 +- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 0712261..389cce3 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -182,33 +182,49 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model resultMessage = {} messages = <%= js_app_name %>.Helpers.errorsMessages - _.each(attrs, (value, key) -> + _.each(attrs, (value, key) => values = _.compact( (validates[key] ||= "").split(" ") ) - for value in values + for validation in values + appliedValidations = true + value = validation.split(":")[0] + action = validation.split(":")[1] - switch value - when "presence" - if _.isEmpty( $.trim( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.blank) + if @isNew() is true and action is "onUpdate" + appliedValidations = false - when "numericality" - unless (/^\d+\.?\d+$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.not_a_number) + if @isNew() is false and action is "onCreate" + appliedValidations = false - when "email" - unless ( /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.invalid_email) + if appliedValidations is true - when "rfc" - unless ( /^([A-Z|a-z|&]{3}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)(\w{2})([A-Z|a-z|0-9])$|^([A-Z|a-z]{4}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)((\w{2})([A-Z|a-z|0-9])){0,3}$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.invalid) + switch value + when "presence" + if _.isEmpty( $.trim( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.blank) - when "zip_code" - unless ( /^\d{5}$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.invalid) + when "numericality" + unless (/^\d+\.?\d+$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.not_a_number) - else false + when "email" + unless ( /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.invalid_email) + + when "rfc" + unless ( /^([A-Z|a-z|&]{3}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)(\w{2})([A-Z|a-z|0-9])$|^([A-Z|a-z]{4}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)((\w{2})([A-Z|a-z|0-9])){0,3}$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.invalid) + + when "zip_code" + unless ( /^\d{5}$/.test( attrs[key] ) ) + (resultMessage[key] ||= []).push(messages.invalid) + + when "equalTo" + unless attrs[key] is @get(action) + message = "#{messages.equal_to} #{@humanAttributeName(action)}" + (resultMessage[key] ||= []).push(message) + + else false ) if _.isEmpty(resultMessage) diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index bb84543..3d4ed8d 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -52,7 +52,7 @@ too_long: one: "es demasiado largo (máximo 1 caracter)" other: "es demasiado largo (máximo %{count} caracteres)" - equal_to: "debe ser igual a %{count}" + equal_to: "debe ser igual a" wrong_length: one: "longitud errónea (debe ser de 1 caracter)" other: "longitud errónea (debe ser de %{count} caracteres)" diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index 5a306d7..186b44d 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -37,8 +37,11 @@ function setValues(el, model, name){ var attrs = {}; var nestedObject = getNestedObject(el, model); + var inputValue = el.val(); - attrs[name] = el.val(); + if (inputValue === "") inputValue = null; + + attrs[name] = inputValue; nestedObject.set(attrs); return true; } From 56ba3ea8ddcc9602d2cec251dcbae2e8ed679c8e Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 7 Nov 2011 11:53:49 -0600 Subject: [PATCH 46/78] Added support for HABTM checkboxes --- .../assets/javascripts/backbone_datalink.js | 86 ++++++++++++++----- 1 file changed, 64 insertions(+), 22 deletions(-) diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index 186b44d..220ca2f 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -1,15 +1,20 @@ (function($) { + function getNestedName(el){ + var nestedName = el.attr("name").replace("[]", ""); + var nesteds = nestedName.split("["); + + for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") + return nesteds[nesteds.length-1]; + } + function getNestedObject(el, model){ var nestedName = el.attr("name"); var nesteds = nestedName.split("[") var nestedObject = null; - for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") - var name = nesteds[nesteds.length-1]; - for (var i in nesteds) { - var value = nesteds[i]; + var value = nesteds[i].replace("]", ""); nestedObject = nestedObject == null ? model : nestedObject; if ( /^.+_attributes$/.test(value) ) { value = value.replace("_attributes", ""); @@ -22,9 +27,13 @@ return nestedObject; } - function setSelectedValueForInput(container, el, model, name){ - var nestedObject = getNestedObject(el, model); + function setSelectedValueForInput(container, el, nestedObject){ + var name = getNestedName(el); var value = nestedObject.get(name) + + if ( el.is("input:text") ) + el.val(value) + if ( el.is("select") ) el.find("option[value=\""+value+"\"]").attr('selected', true); @@ -32,13 +41,46 @@ var radioName = el.attr("name"); container.find("input[name=\""+radioName+"\"][value=\""+value+"\"]:radio").attr('checked', true); } + + if ( el.is("input:checkbox") ) { + // HABTM + if ( /_ids$/.test(name) ) { + var list = (value === null || value === undefined) ? [] : value; + var checkboxValue = parseInt(el.val(), 10); + if ( _.include(list, checkboxValue) ) + el.attr("checked", true); + } else { + var booleanValue = ( el.val() === "true" || el.val() === "1" ) ? true : false; + var shouldMarked = ( value === booleanValue ) ? true : false; + el.attr("checked", shouldMarked) + } + } } - function setValues(el, model, name){ + function setValues(container, el, nestedObject){ var attrs = {}; - var nestedObject = getNestedObject(el, model); + var name = getNestedName(el); var inputValue = el.val(); + if ( el.is("input:checkbox") ) { + // HABTM + if ( /_ids$/.test(name) ) { + var checkeds = container.find("input[name$=\"_ids][]\"]:checkbox:checked"); + inputValue = []; + for(var i = 0, l = checkeds.length; i < l; i++){ + var checkbox = $(checkeds[i]); + inputValue.push(checkbox.val()); + } + } else { + if ( el.is(":checked") ) + inputValue = el.val(); + else { + var checkboxName = el.attr("name"); + inputValue = el.parent().find("input[type=\"hidden\"][name=\""+checkboxName+"\"]").val(); + } + } + } + if (inputValue === "") inputValue = null; attrs[name] = inputValue; @@ -46,30 +88,30 @@ return true; } + function bindChangeEvents(container, el, nestedObject){ + var name = getNestedName(el); + nestedObject.bind("change:" + name, function() { + return setSelectedValueForInput(container, el, nestedObject); + }); + } + return $.extend($.fn, { backboneLink: function(model) { var container = $(this); container.find(":input").each(function() { - var el, name, nestedName, nesteds, nestedObject; + var el, nestedObject; el = $(this); - nestedName = el.attr("name"); - nesteds = nestedName.split("[") nestedObject = getNestedObject(el, model); - for(var i in nesteds) nesteds[i] = nesteds[i].replace("]", "") - name = nesteds[nesteds.length-1]; - - setSelectedValueForInput(container, el, model, name); + setSelectedValueForInput(container, el, nestedObject); + bindChangeEvents(container, el, nestedObject); - nestedObject.bind("change:" + name, function() { - return el.val(nestedObject.get(name)); - }); - return $(this).bind("change", function() { - el = $(this); - return setValues(el, model, name); + return el.bind("change", function() { + return setValues(container, el, nestedObject); }); + }); - return $(this); + return container; } }); })(jQuery); From dd77539905f76bbec6e7baa092d2d766b5aae659 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Tue, 15 Nov 2011 12:35:47 -0600 Subject: [PATCH 47/78] Fixed bug with check_box checked --- vendor/assets/javascripts/backbone_datalink.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vendor/assets/javascripts/backbone_datalink.js b/vendor/assets/javascripts/backbone_datalink.js index 220ca2f..5ebc402 100644 --- a/vendor/assets/javascripts/backbone_datalink.js +++ b/vendor/assets/javascripts/backbone_datalink.js @@ -50,8 +50,9 @@ if ( _.include(list, checkboxValue) ) el.attr("checked", true); } else { - var booleanValue = ( el.val() === "true" || el.val() === "1" ) ? true : false; - var shouldMarked = ( value === booleanValue ) ? true : false; + var inputValue = _.include([true, "true", 1, "1"], el.val()); + var booleanValue = _.include([true, "true", 1, "1"], value); + var shouldMarked = inputValue === booleanValue; el.attr("checked", shouldMarked) } } From 366b69a5e5aa6ee5b129d0b61c2a248621583192 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 21 Nov 2011 20:02:08 -0600 Subject: [PATCH 48/78] Added Inheritance Module --- .../backbone/install/install_generator.rb | 6 +++- .../backbone/install/templates/app.coffee | 3 ++ .../templates/modules/inheritance.coffee | 29 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 lib/generators/backbone/install/templates/modules/inheritance.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index da4c5d6..53040de 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -45,7 +45,7 @@ def inject_in_application_helper end def create_dir_layout - %W{routers models views}.each do |dir| + %W{routers models views modules}.each do |dir| empty_directory "app/assets/javascripts/backbone/#{dir}" create_file "app/assets/javascripts/backbone/#{dir}/.gitkeep" unless options[:skip_git] end @@ -87,6 +87,10 @@ def create_backbone_responses template "backbone_responses.rb", "lib/backbone_responses.rb" end + def create_inheritance_module_file + template "modules/inheritance.rb", "app/assets/javascripts/backbone/modules/inheritance.js.coffee" + end + end end end diff --git a/lib/generators/backbone/install/templates/app.coffee b/lib/generators/backbone/install/templates/app.coffee index 2d1b479..88ab0d2 100644 --- a/lib/generators/backbone/install/templates/app.coffee +++ b/lib/generators/backbone/install/templates/app.coffee @@ -1,5 +1,6 @@ #= require_self #= require ./helpers +#= require_tree ./modules #= require ./models/base_model #= require ./models/base_collection #= require_tree ./models @@ -12,3 +13,5 @@ window.<%= js_app_name %> = Collections: {} Routers: {} Views: {} + +window.Modules = {} diff --git a/lib/generators/backbone/install/templates/modules/inheritance.coffee b/lib/generators/backbone/install/templates/modules/inheritance.coffee new file mode 100644 index 0000000..0609198 --- /dev/null +++ b/lib/generators/backbone/install/templates/modules/inheritance.coffee @@ -0,0 +1,29 @@ +Modules.Inheritance = + + include: (obj) -> + inheritanceKeywords = ['included', 'beforeInitialize', 'afterInitialize', 'beforeRemove'] + + classMethods = obj.classMethods || {} + classMethods = classMethods() if _.isFunction classMethods + + for key, value of classMethods when key not in inheritanceKeywords + @[key] = value + + instanceMethods = obj.instanceMethods || {} + instanceMethods = instanceMethods() if _.isFunction instanceMethods + + for key, value of instanceMethods when key not in inheritanceKeywords + # Assign properties to the prototype + @::[key] = value + + obj.included?.apply(@) + + @::_afterInitialize ||= [] + @::_beforeInitialize ||= [] + @::_beforeRemove ||= [] + + @::_beforeInitialize.push obj.beforeInitialize if obj.beforeInitialize? + @::_afterInitialize.push obj.afterInitialize if obj.afterInitialize? + @::_beforeRemove.push obj.beforeRemove if obj.beforeRemove? + + this From e0549aac2871a105081d9862cd009b512652a665 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 21 Nov 2011 20:15:35 -0600 Subject: [PATCH 49/78] Extend BaseView With Inheritance Module --- .../install/templates/base_view.coffee | 41 ++++++++++++++++--- .../backbone/install/templates/helpers.coffee | 2 +- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index fcae101..b24c359 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -1,6 +1,31 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View + _.extend @, Modules.Inheritance + + constructor: -> + @beforeInitialize() + super(arguments...) + @afterInitialize() + + # Callbacks + # ========================================================== + beforeInitialize: -> + _.each(@_beforeInitialize, (callback, key) => + callback?.apply(@) + ) + + afterInitialize: -> + _.each(@_afterInitialize, (callback, key) => + callback?.apply(@) + ) + + beforeRemove: -> + _.each(@_beforeRemove, (callback, key) => + callback?.apply(@) + ) + # Defaults Events + # ========================================================== events: "click .destroy" : "destroy" "click div.pagination a" : "pagination" @@ -67,7 +92,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View else @renderErrors(@model, @model.errors) # Errors - # ________________________________________________________________________ + # ========================================================== renderErrors: (model, errors) -> fullErrors = {} _.each(errors, (messages, key) -> @@ -78,7 +103,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View <%= js_app_name %>.Helpers.renderErrors(fullErrors) # Pagination - # ________________________________________________________________________ + # ========================================================== pagination: (e, collection) -> e.preventDefault() link = $(e.currentTarget) @@ -105,12 +130,18 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View # builder pages for number in [1..pagination.total_pages] - page = {} + page = {} page.liKlass = "active" if pagination.current_page is number - page.text = number - page.path = "#{pagination.resources_path}?page=#{number}" + page.text = number + page.path = "#{pagination.resources_path}?page=#{number}" pagination.pages.push(page) @$("#pagination-container").html( $("#backboneTemplatesPagination").tmpl(pagination) ) + + # Remove Callbacks in beforeRemove() function if needed + # ========================================================== + remove: -> + @beforeRemove() + super() diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index 3d4ed8d..1d7cd35 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -76,7 +76,7 @@ String.prototype.toUnderscore = () -> replace( /^_/, '' ) String.prototype.toCamelize = (type) -> - value = @replace(/(_| )/, "-"). + value = @replace(/(_| )/g, "-"). replace(/(\-[a-z])/g, ($1) -> $1.toUpperCase().replace('-','') ). replace( /^([a-z])/g, ($1) -> $1.toUpperCase() ) From e60a07927f7ca3ed121d791f667b72e74ddcd29d Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 21 Nov 2011 20:19:07 -0600 Subject: [PATCH 50/78] Edit In Place (EIP) Module was added --- .../backbone/install/install_generator.rb | 6 +- .../install/templates/modules/eip.coffee | 205 ++++++++++++++++++ 2 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 lib/generators/backbone/install/templates/modules/eip.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 53040de..c788012 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -88,7 +88,11 @@ def create_backbone_responses end def create_inheritance_module_file - template "modules/inheritance.rb", "app/assets/javascripts/backbone/modules/inheritance.js.coffee" + template "modules/inheritance.coffee", "app/assets/javascripts/backbone/modules/inheritance.js.coffee" + end + + def create_eip_module_file + template "modules/eip.coffee", "app/assets/javascripts/backbone/modules/eip.js.coffee" end end diff --git a/lib/generators/backbone/install/templates/modules/eip.coffee b/lib/generators/backbone/install/templates/modules/eip.coffee new file mode 100644 index 0000000..4872bca --- /dev/null +++ b/lib/generators/backbone/install/templates/modules/eip.coffee @@ -0,0 +1,205 @@ +Modules.EIP = (options = {}) -> + + # Callbacks + # ========================================================== + beforeInitialize: -> + @eipBuildFunctions() + _.extend @events, @eipEvents() + + afterInitialize: -> + @eipBindCallbacks() + @eipSetDefault() + + beforeRemove: -> + @eipUnbindCallbacks() + + + instanceMethods: () -> + + options.eipNodes ||= {} + + _.extend options, + + # Events For EIP + # ================================================================ + eipEvents: -> + events = { + "click .eip-btn" : "eipPrintListBtn" + "click .eip-node" : "eipShowNode" + "click .delete-eip" : "eipDestroyNested" + "click .eip-delete-node" : "eipDestroyNested" + } + _.each(@eipNodes, (node, key) -> + events["click .add_#{key}"] = "eip_create_#{key}".toCamelize("lower") + ) + events + + # Print Functions For EIP + # ================================================================ + + # Print List + eipPrintList: (nodeName, eipAnimate = true) -> + container = this.$("#eip-container") + + if eipAnimate + $('html, body').animate({ scrollTop: container.offset().top }, 'slow') + + if nodeName? + eipListTemplate = @eipGetListTemplate(nodeName) + collection = @eipGetCollection(nodeName) + + container.html eipListTemplate + + collection.each(@eipPrintNode, @) + + # Print Node And Form + eipPrintNodeWithForm: (nested_model) -> + @eipPrintNode nested_model, true + @eipPrintForm nested_model + + # Print Node + eipPrintNode: (nested_model, nodeActive = false) -> + dom = @eipGetNodeTemplate(nested_model.paramRoot, nested_model) + if nested_model.eip_node_dom? and nested_model.eip_node_dom.is(":visible") + nested_model.eip_node_dom.replaceWith dom + else + @$("#eip-list").append dom + nested_model.bind("change", @eipPrintNode, @) + + nested_model.eip_node_dom = dom + $(dom).data('nested_model', nested_model) + + @eipSetNodeActive dom if nodeActive + + # Print Form + eipPrintForm: (nested_model) -> + dom = @eipGetFormTemplate(nested_model.paramRoot, nested_model) + container = @$("#eip-form") + + container.html dom.backboneLink(@model) + $('html, body').animate({ scrollTop: container.offset().top }, 'slow') + + nested_model.eip_form_dom = dom + dom.find(".delete-eip").data('nested_model', nested_model) + + eipShowNode: (e) -> + unless $(e.target).is("a.eip-delete-node") + node = $(e.currentTarget) + @eipSetNodeActive node + nested_model = node.data('nested_model') + @eipPrintForm nested_model + + eipSetNodeActive: (node) -> + @$('.eip-node').removeClass('active') + node.addClass('active') + + eipPrintListBtn: (e) -> + e.preventDefault() + link = $(e.currentTarget) + + if link.is(".info") + @eipPrintList null # Just run the animation + else + nodeName = @eipGetNodeName(link) + @eipPrintList nodeName + @eipSetBtnListActive(link) + + # Destroy Functions For EIP + # ================================================================ + eipDestroyNested: (e) -> + e.preventDefault() + + msg = $(e.currentTarget).attr("data-confirm") + if msg? and !confirm(msg) then return false + + dom = $(e.currentTarget) + model_object = dom.data('nested_model') + + if dom.data('nested_model') is undefined + model_object = dom.parents('.eip-node').data('nested_model') + + model_object.destroy() + + eipRemoveNestedFromDom: (nested_model) -> + nested_model.eip_form_dom?.remove?() + nested_model.eip_node_dom?.remove?() + + # Get Templates For EIP + # ================================================================ + eipGetNodeTemplate: (nodeName, nested_model) -> + templateName = "#{nodeName}_template".toCamelize() + @["eipNode#{templateName}"](nested_model.toJSON(true)) + + eipGetFormTemplate: (nodeName, nested_model) -> + templateName = "#{nodeName}_template".toCamelize() + @["eipForm#{templateName}"](nested_model.toJSON(true)) + + eipGetListTemplate: (nodeName) -> + templateName = "#{nodeName}_template".toCamelize() + @["eipList#{templateName}"]() + + eipGetCollection: (nodeName) -> + collection = @eipNodes[nodeName].collection + @model[collection] + + + # Build Functions For EIP + # ================================================================ + eipBuildFunctions: () -> + _.each(@eipNodes, (node, key) => + templateName = "#{key}_template".toCamelize() + functionName = "eip_create_#{key}".toCamelize("lower") + + # Templates + @["eipNode#{templateName}"] = (data) -> $("#eipNode#{templateName}").tmpl(data) + @["eipForm#{templateName}"] = (data) -> $("#eipForm#{templateName}").tmpl(data) + @["eipList#{templateName}"] = (data) -> $("#eipList#{templateName}").tmpl(data) + + # Functions + @[functionName] = (e) -> + e.preventDefault() + @eipGetCollection(key).add() + ) + + # Bind Add Callback For Collections + # ================================================================ + eipBindCallbacks: -> + _.each(@eipNodes, (node, key) => + @eipGetCollection(key).bind("add", @eipPrintNodeWithForm, @) + @eipGetCollection(key).bind("destroy", @eipRemoveNestedFromDom, @) + ) + eipUnbindCallbacks: -> + _.each(@eipNodes, (node, key) => + @eipGetCollection(key).unbind("add", @eipPrintNodeWithForm, @) + @eipGetCollection(key).unbind("destroy", @eipRemoveNestedFromDom, @) + ) + + # Other Functions + # ================================================================ + eipGetNodeName: (link) -> + name = null + _.each(@eipNodes, (node, key) => + name = key if link.is(".eip_#{key}") + ) + name + + eipSetDefault: () -> + if @eipDefault? + _this = @ + $("a.eip_#{@eipDefault}").livequery(() -> + link = $(this) + _this.eipSetBtnListActive(link) + _this.eipPrintList(_this.eipDefault, false) + ) + + eipSetBtnListActive: (link) -> + @$("#eip-buttons .eip-btn").removeClass("info") + link.addClass("info") + + + # Class Methods + # ================================================================ + + #classMethods: + + #class_method: -> From acc6527e250fb7dd276d8c741555a22829bec136 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 10:00:47 -0600 Subject: [PATCH 51/78] Added collection_scopes method in backbone_responses --- .../backbone/install/templates/backbone_responses.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/generators/backbone/install/templates/backbone_responses.rb b/lib/generators/backbone/install/templates/backbone_responses.rb index 34899ad..7fdcde0 100644 --- a/lib/generators/backbone/install/templates/backbone_responses.rb +++ b/lib/generators/backbone/install/templates/backbone_responses.rb @@ -51,14 +51,18 @@ def show def collection if paginate? - resources = end_of_association_chain.paginate( + resources = collection_scopes.paginate( :page => (params[:page] || 1), :per_page => resources_per_page) else - resources = end_of_association_chain.all + resources = collection_scopes.all end instance_variable_set("@#{controller_name}" , resources) end + def collection_scopes + end_of_association_chain + end + def resource_public_attributes model = end_of_association_chain object = reload_resource ? resource.reload : resource @@ -71,7 +75,7 @@ def resource_public_attributes end def collection_public_attributes - model = controller_name.classify.constantize + model = end_of_association_chain resources = collection if model.respond_to?(:acts_as_api?) and model.acts_as_api? and model.respond_to?(:"api_accessible_#{api_collection_template}") @@ -106,7 +110,7 @@ def api_collection_template end def api_resource_template - "public" + params[:api_template] || "public" end def paginate? From cb1d1ff92694cf4ea1341e76a5598f0e2484c3a5 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 10:18:29 -0600 Subject: [PATCH 52/78] Added support for I18n && Validation method was changed && Now nested models are validated when saving a model --- .../install/templates/base_model.coffee | 140 ++++++++++++------ 1 file changed, 97 insertions(+), 43 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 389cce3..6ea5ec5 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -1,6 +1,8 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model initialize: (attributes, options) -> + @calculatedAttributes = {} + # Clone de original attributes attributes = _.extend({}, _.clone(attributes)) @@ -32,12 +34,30 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model # Call After Initialize Callback @afterInitialize() - toJSON: ( includeRelations = false ) -> + get : ( key ) -> + that = @ + + if @calculatedAttributes[key] + value = @calculatedAttributes[key] + + if typeof value != 'undefined' + return value + + # fall back to the default backbone behavior + return Backbone.Model.prototype.get.call(this, key) + + + toJSON: ( includeRelations = false, includeCalculated = false ) -> json = _.clone @attributes if includeRelations is true json["#{@paramRoot}_cid"] = "backboneCid_#{@cid}" + if includeCalculated is true + _.each(@calculatedAttributes, (attribute, key) => + json[key] = attribute + ) + # belongsTo _.each(@belongsTo, (relation, key) => @@ -48,6 +68,7 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model if @[key]? and relation.isNested is true if relation.isPolymorphic isnt true json["#{key}_attributes"] = @[key].toJSON(includeRelations) + delete json[key] # include all values to use in Show view for example @@ -67,9 +88,12 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model _.each(@hasMany, (relation, key) => if includeRelations is false + if @[key]? and relation.isNested is true json["#{key}_attributes"] = @[key].toJSON(includeRelations) + delete json[key] + else if @[key]? json[key] = @[key].toJSON(includeRelations) ) @@ -81,6 +105,10 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model delete json[value] ) + # Attributes with null value are eliminated + for _key, _value of json + if _value is null and @hasChanged(_key) is false + delete json[_key] json @@ -116,13 +144,15 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model # Retrieve values from database if foreignKey has changed else if callbackKey? and relation.isNested isnt true + if newValue = @get(relation.foreignKey) if newValue isnt @[key].get("id") url = "/#{relation.route}/#{newValue}" - data = <%= js_app_name %>.Helpers.jsonData(url) - - # Set values in association model - @[key].set(data) if data? + <%= js_app_name %>.Helpers.jsonCallback( + url + (data) => @[key].set(data, {silent: true}) if data? + {api_template: "base"} # params + ) # clear attributes if foreignKey is null else @[key].clear silent: true @@ -166,8 +196,8 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model (relation, key) => values = attributes[key] relation = @buildBelonsToRelation(relation, key) - if values? and relation.isNested is true - @[key] = new <%= js_app_name %>.Models[relation.model] values + if values? and ( relation.isNested is true or relation.resettable is true) + @[key] = new <%= js_app_name %>.Models[relation.model] values ) # hasMany _.each(@hasMany, @@ -180,62 +210,93 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model validates: (attrs, validates = {}) -> resultMessage = {} - messages = <%= js_app_name %>.Helpers.errorsMessages + messages = Modules.I18n.hash().errorsMessages - _.each(attrs, (value, key) => - values = _.compact( (validates[key] ||= "").split(" ") ) + # Each for attributes of the model + _.each(attrs, (attrValue, attrKey) => - for validation in values + for key, validation of validates[attrKey] appliedValidations = true - value = validation.split(":")[0] - action = validation.split(":")[1] + action = validation.on - if @isNew() is true and action is "onUpdate" + if @isNew() is true and action is "update" appliedValidations = false - if @isNew() is false and action is "onCreate" + if @isNew() is false and action is "create" appliedValidations = false if appliedValidations is true - switch value + isEmpty = _.isEmpty( $.trim( attrValue ) ) + + switch key when "presence" - if _.isEmpty( $.trim( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.blank) + if isEmpty + (resultMessage[attrKey] ||= []).push(messages.blank) when "numericality" - unless (/^\d+\.?\d+$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.not_a_number) + if isEmpty is false and /^\d+(\.\d+)?$/.test( attrValue ) is false + (resultMessage[attrKey] ||= []).push(messages.not_a_number) when "email" - unless ( /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.invalid_email) + if isEmpty is false and /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test( attrValue ) is false + (resultMessage[attrKey] ||= []).push(messages.invalid_email) when "rfc" - unless ( /^([A-Z|a-z|&]{3}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)(\w{2})([A-Z|a-z|0-9])$|^([A-Z|a-z]{4}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)((\w{2})([A-Z|a-z|0-9])){0,3}$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.invalid) + if isEmpty is false and /^([A-Z|a-z|&]{3}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)(\w{2})([A-Z|a-z|0-9])$|^([A-Z|a-z]{4}\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)|([02468][048]|[13579][26])0229)((\w{2})([A-Z|a-z|0-9])){0,3}$/.test( attrValue ) is false + (resultMessage[attrKey] ||= []).push(messages.invalid) when "zip_code" - unless ( /^\d{5}$/.test( attrs[key] ) ) - (resultMessage[key] ||= []).push(messages.invalid) + if isEmpty is false and /^\d{5}$/.test( attrValue ) is false + (resultMessage[attrKey] ||= []).push(messages.invalid) + + when "length" + if isEmpty is false + min = validation.min + max = validation.max + attrLength = (attrValue || "").length + + if (min? and attrLength < min) + if min is 1 then lengthMessage = "one" else lengthMessage = "other" + message = (messages.too_short?[lengthMessage] || "").replace("%{count}", min) + (resultMessage[attrKey] ||= []).push(message) + + else if (max? and attrLength > max) + if max is 1 then lengthMessage = "one" else lengthMessage = "other" + message = (messages.too_long?[lengthMessage] || "").replace("%{count}", max) + (resultMessage[attrKey] ||= []).push(message) when "equalTo" - unless attrs[key] is @get(action) - message = "#{messages.equal_to} #{@humanAttributeName(action)}" - (resultMessage[key] ||= []).push(message) + unless attrValue is @get(validation) + message = (messages.equal_to || "").replace("%{count}", @humanAttributeName(validation)) + (resultMessage[attrKey] ||= []).push(message) else false ) - if _.isEmpty(resultMessage) - delete @errors - null + if _.isEmpty(resultMessage) then null else @attributes = _.extend(@attributes, attrs) @errors = resultMessage isValid: () -> - if @validate(@attributes)? then false else true + resultValidation = @validate(@attributes) || {} + + # Run HasMany validations + for key, value of @hasMany when value.isNested is true + @[key].each((model) -> + nestedValidation = model.validate(model.attributes) || {} + resultValidation["#{key}.#{_key}"] = _value for _key, _value of nestedValidation + ) + + # Run BelongsTo validations + for key, value of @belongsTo when value.isNested is true + model = @[key] + nestedValidation = model.validate(model.attributes) || {} + resultValidation["#{key}.#{_key}"] = _value for _key, _value of nestedValidation + + if _.isEmpty resultValidation then true + else @errors = resultValidation includeCidInJson: false @@ -253,19 +314,12 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model afterInitialize: () -> + # I18n support modelName: () -> @paramRoot humanName: () -> - name = <%= js_app_name %>.Helpers.activerecord.models[@paramRoot] - if name? then name else @paramRoot + Modules.I18n.t "activerecord.models.#{@paramRoot}" humanAttributeName: (name) -> - modelAttributes = <%= js_app_name %>.Helpers.activerecord.attributes[@paramRoot] - if modelAttributes? - attribute = modelAttributes[name] - attributeName = if attribute? then attribute else name - else - attributeName = name - - attributeName + Modules.I18n.t "activerecord.attributes.#{@paramRoot}.#{name}" From fcbdf0269f723afe0080bec86b1cafd0201466f8 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 10:20:33 -0600 Subject: [PATCH 53/78] Added support for I18n and flash messages in views --- .../install/templates/base_view.coffee | 64 +++++++++++++------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index b24c359..13c3574 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -30,21 +30,26 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View "click .destroy" : "destroy" "click div.pagination a" : "pagination" + allowAction: (element) -> + message = element.attr("data-confirm") || element.attr("confirm") + !message || confirm(message) + destroy: (e, options = {}) -> - msg = $(e.currentTarget).attr("data-confirm") - if msg? and !confirm(msg) then return false + e.preventDefault() - @model.destroy(options) - @remove() + if @model? + link = $(e.currentTarget) + return false unless @allowAction(link) - return false + @model.destroy(options) + @remove() save: (e, options = {}) -> e.preventDefault() e.stopPropagation() - msg = $(e.currentTarget).attr("confirm") - if msg? and !confirm(msg) then return false + form = $(e.currentTarget) + return false unless @allowAction(form) options = _.extend( success: (model) => @@ -54,7 +59,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options) - if @model.isValid() + if @model.isValid() is true @collection.create(@model, success: (model, jqXHR) => window.router._editedModels = [] @@ -69,8 +74,8 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View e.preventDefault() e.stopPropagation() - msg = $(e.currentTarget).attr("confirm") - if msg? and !confirm(msg) then return false + form = $(e.currentTarget) + return false unless @allowAction(form) options = _.extend( success : (model) => @@ -80,7 +85,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options) - if @model.isValid() + if @model.isValid() is true @model.save(null, success: (model, jqXHR) => window.router._editedModels = [] @@ -96,24 +101,29 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View renderErrors: (model, errors) -> fullErrors = {} _.each(errors, (messages, key) -> - name = $('label[for="' + model.paramRoot + '_' + key + '"]').text() || key + name = model.humanAttributeName(key) for message in messages - (fullErrors.errors ||= []).push({name: name, message: message}) + (fullErrors.messages ||= []).push({name: name, message: message}) ) - <%= js_app_name %>.Helpers.renderErrors(fullErrors) + <%= js_app_name %>.Helpers.renderError(fullErrors) # Pagination # ========================================================== pagination: (e, collection) -> e.preventDefault() - link = $(e.currentTarget) - li = link.closest("li") + link = $(e.currentTarget) + li = link.closest("li") + container = link.closest("#pagination-container") unless li.is(".active, .prev.disabled, .next.disabled") - href = link.attr("href") - data = <%= js_app_name %>.Helpers.jsonData href - collection.pagination = data.pagination - collection.reset data.resources + unless container.attr("data-waiting") + container.attr("data-waiting", true) + href = link.attr("href") + <%= js_app_name %>.Helpers.jsonCallback(href, (data) -> + collection.pagination = data.pagination + collection.reset data.resources + container.removeAttr("data-waiting") + ) renderPagination: (collection) -> pagination = collection.pagination || {} @@ -145,3 +155,17 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View remove: -> @beforeRemove() super() + + # I18n support + t: (route = "") -> + Modules.I18n.t route + + # Falsh Messages + flash: (type, messages = "") -> + if _.include <%= js_app_name %>.Config.flashes, type + if _.isString messages + messages = {messages: [{message: messages}]} + + flashTemplate = "render_#{type}".toCamelize("lower") + <%= js_app_name %>.Helpers[flashTemplate]? messages + From 8377f585cc4b6a823c2395f57ebd9905bc533238 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 11:24:19 -0600 Subject: [PATCH 54/78] Added ajax method --- .../backbone/install/templates/helpers.coffee | 82 ++++++------------- 1 file changed, 23 insertions(+), 59 deletions(-) diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index 1d7cd35..ce3a173 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -15,73 +15,37 @@ jsonCallback: (url, callback, params = {}) -> $.getJSON(url, params, (data) -> callback?(data) ) + ajax: (options = {}) -> + return if !options.url + + settings = + type: "GET" + data: {} + dataType: "json" + beforeSend: (xhr) -> + token = $('meta[name="csrf-token"]').attr('content') + xhr.setRequestHeader('X-CSRF-Token', token) if token + + _.extend settings, options + + $.ajax settings + # Renders For Alers Messages - renderWarnings: (data) -> + renderWarning: (data) -> $("#alerts_container").html( $("#backboneWarningAlert").tmpl(data) ) - renderErrors: (data) -> + renderError: (data) -> $('.alert-message').remove() container = $(".columns form:first") - container.prepend( $("#backboneErrorAlert").tmpl(data) ) - $('html, body').animate({ scrollTop: container.offset().top - 45 }, 'slow') + + if container.offset()? + container.prepend( $("#backboneErrorAlert").tmpl(data) ) + $('html, body').animate({ scrollTop: container.offset().top - 45 }, 'slow') + else + $("#alerts_container").html( $("#backboneErrorAlert").tmpl(data) ) renderSuccess: (data) -> $("#alerts_container").html( $("#backboneSuccessAlert").tmpl(data) ) renderInfo: (data) -> $("#alerts_container").html( $("#backboneInfoAlert").tmpl(data) ) - - errorsMessages: - inclusion: "no está incluído en la lista" - exclusion: "está reservado" - invalid: "es inválido" - record_invalid: "es inválido" - invalid_date: "es una fecha inválida" - confirmation: "no coincide con la confirmación" - blank: "no puede estar en blanco" - empty: "no puede estar vacío" - not_a_number: "no es un número" - taken: "ya ha sido tomado" - less_than: "debe ser menor que %{count}" - less_than_or_equal_to: "debe ser menor o igual que %{count}" - greater_than: "debe ser mayor que %{count}" - greater_than_or_equal_to: "debe ser mayor o igual que %{count}" - too_short: - one: "es demasiado corto (mínimo 1 caracter)" - other: "es demasiado corto (mínimo %{count} caracteres)" - too_long: - one: "es demasiado largo (máximo 1 caracter)" - other: "es demasiado largo (máximo %{count} caracteres)" - equal_to: "debe ser igual a" - wrong_length: - one: "longitud errónea (debe ser de 1 caracter)" - other: "longitud errónea (debe ser de %{count} caracteres)" - accepted: "debe ser aceptado" - even: "debe ser un número par" - odd: "debe ser un número non" - invalid_email: "no es una dirección de correo electrónico válida" - - activerecord: - models: - model_name: "Human Model Name" - - attributes: - model_name: - attribute: "Human Attribute Name" - - -# Strings -String.prototype.toUnderscore = () -> - @replace( /([A-Z])/g, ($1) -> "_"+$1.toLowerCase() ). - replace( /^_/, '' ) - -String.prototype.toCamelize = (type) -> - value = @replace(/(_| )/g, "-"). - replace(/(\-[a-z])/g, ($1) -> $1.toUpperCase().replace('-','') ). - replace( /^([a-z])/g, ($1) -> $1.toUpperCase() ) - - switch type - when "lower" then value = value.replace( /^([A-Z])/g, ($1) -> $1.toLowerCase() ) - else value - - value From f1c47584e9fe67fdc49709a06f704d63029fe460 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 11:29:49 -0600 Subject: [PATCH 55/78] Added support for render errors messages for EIP models --- .../backbone/install/templates/modules/eip.coffee | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/generators/backbone/install/templates/modules/eip.coffee b/lib/generators/backbone/install/templates/modules/eip.coffee index 4872bca..99fc197 100644 --- a/lib/generators/backbone/install/templates/modules/eip.coffee +++ b/lib/generators/backbone/install/templates/modules/eip.coffee @@ -109,15 +109,16 @@ Modules.EIP = (options = {}) -> eipDestroyNested: (e) -> e.preventDefault() - msg = $(e.currentTarget).attr("data-confirm") - if msg? and !confirm(msg) then return false - dom = $(e.currentTarget) model_object = dom.data('nested_model') - if dom.data('nested_model') is undefined + if model_object is undefined or model_object is null model_object = dom.parents('.eip-node').data('nested_model') + unless model_object.isNew() + msg = $(e.currentTarget).attr("data-confirm") + if msg? and !confirm(msg) then return false + model_object.destroy() eipRemoveNestedFromDom: (nested_model) -> @@ -167,11 +168,13 @@ Modules.EIP = (options = {}) -> _.each(@eipNodes, (node, key) => @eipGetCollection(key).bind("add", @eipPrintNodeWithForm, @) @eipGetCollection(key).bind("destroy", @eipRemoveNestedFromDom, @) + @eipGetCollection(key).bind("error", @renderErrors, @) ) eipUnbindCallbacks: -> _.each(@eipNodes, (node, key) => @eipGetCollection(key).unbind("add", @eipPrintNodeWithForm, @) @eipGetCollection(key).unbind("destroy", @eipRemoveNestedFromDom, @) + @eipGetCollection(key).unbind("error", @renderErrors, @) ) # Other Functions From 1c44cfb08cdab2dd7daa62e5681087e38334a345 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 11:43:12 -0600 Subject: [PATCH 56/78] Added config files && Added locale files --- .../backbone/install/install_generator.rb | 15 +++++++- .../backbone/install/templates/app.coffee | 7 +++- .../templates/config/locales/es-MX.coffee | 37 +++++++++++++++++++ .../install/templates/config/string.coffee | 14 +++++++ .../install/templates/modules/i18n.coffee | 14 +++++++ 5 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 lib/generators/backbone/install/templates/config/locales/es-MX.coffee create mode 100644 lib/generators/backbone/install/templates/config/string.coffee create mode 100644 lib/generators/backbone/install/templates/modules/i18n.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index c788012..dc84055 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -45,7 +45,7 @@ def inject_in_application_helper end def create_dir_layout - %W{routers models views modules}.each do |dir| + %W{routers models views modules config}.each do |dir| empty_directory "app/assets/javascripts/backbone/#{dir}" create_file "app/assets/javascripts/backbone/#{dir}/.gitkeep" unless options[:skip_git] end @@ -95,6 +95,19 @@ def create_eip_module_file template "modules/eip.coffee", "app/assets/javascripts/backbone/modules/eip.js.coffee" end + def create_i18n_module_file + template "modules/i18n.coffee", "app/assets/javascripts/backbone/modules/i18n.js.coffee" + end + + def create_locale_files + empty_directory "app/assets/javascripts/backbone/config/locales" + template "config/locales/es-MX.coffee", "app/assets/javascripts/backbone/config/locales/es-MX.js.coffee" + end + + def create_config_files + template "config/string.coffee", "app/assets/javascripts/backbone/config/string.js.coffee" + end + end end end diff --git a/lib/generators/backbone/install/templates/app.coffee b/lib/generators/backbone/install/templates/app.coffee index 88ab0d2..c420756 100644 --- a/lib/generators/backbone/install/templates/app.coffee +++ b/lib/generators/backbone/install/templates/app.coffee @@ -1,6 +1,7 @@ #= require_self -#= require ./helpers +#= require_tree ./config #= require_tree ./modules +#= require ./helpers #= require ./models/base_model #= require ./models/base_collection #= require_tree ./models @@ -13,5 +14,9 @@ window.<%= js_app_name %> = Collections: {} Routers: {} Views: {} + Locales: {} + Config: + default_locale:"es-MX" + flashes: ["warning", "error", "success", "info"] window.Modules = {} diff --git a/lib/generators/backbone/install/templates/config/locales/es-MX.coffee b/lib/generators/backbone/install/templates/config/locales/es-MX.coffee new file mode 100644 index 0000000..1025431 --- /dev/null +++ b/lib/generators/backbone/install/templates/config/locales/es-MX.coffee @@ -0,0 +1,37 @@ +MultivaAtm.Locales["es-MX"] = + errorsMessages: + inclusion: "no está incluído en la lista" + exclusion: "está reservado" + invalid: "es inválido" + record_invalid: "es inválido" + invalid_date: "es una fecha inválida" + confirmation: "no coincide con la confirmación" + blank: "no puede estar en blanco" + empty: "no puede estar vacío" + not_a_number: "no es un número" + taken: "ya ha sido tomado" + less_than: "debe ser menor que %{count}" + less_than_or_equal_to: "debe ser menor o igual que %{count}" + greater_than: "debe ser mayor que %{count}" + greater_than_or_equal_to: "debe ser mayor o igual que %{count}" + too_short: + one: "es demasiado corto (mínimo 1 caracter)" + other: "es demasiado corto (mínimo %{count} caracteres)" + too_long: + one: "es demasiado largo (máximo 1 caracter)" + other: "es demasiado largo (máximo %{count} caracteres)" + equal_to: "debe ser igual a %{count}" + wrong_length: + one: "longitud errónea (debe ser de 1 caracter)" + other: "longitud errónea (debe ser de %{count} caracteres)" + accepted: "debe ser aceptado" + even: "debe ser un número par" + odd: "debe ser un número non" + invalid_email: "no es una dirección de correo electrónico válida" + + activerecord: + models: {} # Human Model Name + + attributes: + model: {} # Model Attributes + diff --git a/lib/generators/backbone/install/templates/config/string.coffee b/lib/generators/backbone/install/templates/config/string.coffee new file mode 100644 index 0000000..3566dad --- /dev/null +++ b/lib/generators/backbone/install/templates/config/string.coffee @@ -0,0 +1,14 @@ +String.prototype.toUnderscore = () -> + @replace( /([A-Z])/g, ($1) -> "_"+$1.toLowerCase() ). + replace( /^_/, '' ) + +String.prototype.toCamelize = (type) -> + value = @replace(/(_| )/g, "-"). + replace(/(\-[a-z])/g, ($1) -> $1.toUpperCase().replace('-','') ). + replace( /^([a-z])/g, ($1) -> $1.toUpperCase() ) + + switch type + when "lower" then value = value.replace( /^([A-Z])/g, ($1) -> $1.toLowerCase() ) + else value + + value diff --git a/lib/generators/backbone/install/templates/modules/i18n.coffee b/lib/generators/backbone/install/templates/modules/i18n.coffee new file mode 100644 index 0000000..0c0b62e --- /dev/null +++ b/lib/generators/backbone/install/templates/modules/i18n.coffee @@ -0,0 +1,14 @@ +Modules.I18n = + locale: <%= js_app_name %>.Config.default_locale + + hash: -> <%= js_app_name %>.Locales[@locale] || {} + + t: (route = "") -> + hash = @hash() + keys = route.split(".") + + for key in keys + if hash[key]? then hash = hash[key] + else hash = key + + hash From f9e9f2af8f71d4826ccff187ced5ed046be961f9 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 11:46:26 -0600 Subject: [PATCH 57/78] Some changes in Model template --- backbone-rails.gemspec | 2 +- .../install/templates/config/locales/es-MX.coffee | 2 +- lib/generators/backbone/model/templates/model.coffee | 8 +++++--- lib/generators/backbone/scaffold/templates/model.coffee | 8 +++++--- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/backbone-rails.gemspec b/backbone-rails.gemspec index e9e9802..a324572 100644 --- a/backbone-rails.gemspec +++ b/backbone-rails.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "rails-backbone" s.version = "0.5.4" - s.authors = ["Ryan Fitzgerald", "Code Brew Studios"] + s.authors = ["Ryan Fitzgerald", "Code Brew Studios", "Jairo Vazquez"] s.email = ["ryan@codebrewstudios.com"] s.homepage = "http://github.com/codebrew/backbone-rails" diff --git a/lib/generators/backbone/install/templates/config/locales/es-MX.coffee b/lib/generators/backbone/install/templates/config/locales/es-MX.coffee index 1025431..f915121 100644 --- a/lib/generators/backbone/install/templates/config/locales/es-MX.coffee +++ b/lib/generators/backbone/install/templates/config/locales/es-MX.coffee @@ -1,4 +1,4 @@ -MultivaAtm.Locales["es-MX"] = +<%= js_app_name %>.Locales["es-MX"] = errorsMessages: inclusion: "no está incluído en la lista" exclusion: "está reservado" diff --git a/lib/generators/backbone/model/templates/model.coffee b/lib/generators/backbone/model/templates/model.coffee index 9e977c9..242b4f9 100644 --- a/lib/generators/backbone/model/templates/model.coffee +++ b/lib/generators/backbone/model/templates/model.coffee @@ -9,11 +9,13 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel validate: (attrs) -> return @validates(attrs, { - # example: : "presence" + # example + # : + # presence: true }) -<%= model_namespace %>.paramRoot = '<%= singular_name %>' -<%= model_namespace %>.collectionRoute = '<%= plural_name %>' + @paramRoot = '<%= singular_name %>' + @collectionRoute = '<%= plural_name %>' class <%= collection_namespace %>Collection extends <%= js_app_name %>.Collections.BaseCollection model: <%= model_namespace %> diff --git a/lib/generators/backbone/scaffold/templates/model.coffee b/lib/generators/backbone/scaffold/templates/model.coffee index 052f153..783b33b 100644 --- a/lib/generators/backbone/scaffold/templates/model.coffee +++ b/lib/generators/backbone/scaffold/templates/model.coffee @@ -9,11 +9,13 @@ class <%= model_namespace %> extends <%= js_app_name %>.Models.BaseModel validate: (attrs) -> return @validates(attrs, { - # example: : "presence" + # example + # : + # presence: true }) -<%= model_namespace %>.paramRoot = '<%= singular_name %>' -<%= model_namespace %>.collectionRoute = '<%= plural_name %>' + @paramRoot = '<%= singular_name %>' + @collectionRoute = '<%= plural_name %>' class <%= collection_namespace %>Collection extends <%= js_app_name %>.Collections.BaseCollection model: <%= model_namespace %> From fd9e1bd57498592eb7136e45ab78bc8fe99e5fbd Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Mon, 28 Nov 2011 13:05:25 -0600 Subject: [PATCH 58/78] Modified backbone alerts templates --- .../backbone/install/templates/alerts/_error_alert.haml | 2 +- .../backbone/install/templates/alerts/_info_alert.haml | 7 +++++-- .../backbone/install/templates/alerts/_success_alert.haml | 7 +++++-- .../backbone/install/templates/alerts/_warning_alert.haml | 7 +++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/generators/backbone/install/templates/alerts/_error_alert.haml b/lib/generators/backbone/install/templates/alerts/_error_alert.haml index 9b1f6dd..1588743 100644 --- a/lib/generators/backbone/install/templates/alerts/_error_alert.haml +++ b/lib/generators/backbone/install/templates/alerts/_error_alert.haml @@ -1,7 +1,7 @@ .alert-message.error.block-message %a.close{:href =>"#"} x - {{each errors}} + {{each messages}} %p %strong ${name} ${message} {{/each}} diff --git a/lib/generators/backbone/install/templates/alerts/_info_alert.haml b/lib/generators/backbone/install/templates/alerts/_info_alert.haml index 8e2dcd8..487d392 100644 --- a/lib/generators/backbone/install/templates/alerts/_info_alert.haml +++ b/lib/generators/backbone/install/templates/alerts/_info_alert.haml @@ -1,4 +1,7 @@ -.alert-message.warning +.alert-message.info.block-message %a.close{:href =>"#"} x + + {{each messages}} %p - %strong Ocurrio un super info + %strong ${message} + {{/each}} diff --git a/lib/generators/backbone/install/templates/alerts/_success_alert.haml b/lib/generators/backbone/install/templates/alerts/_success_alert.haml index 5ee1a32..e31cf4a 100644 --- a/lib/generators/backbone/install/templates/alerts/_success_alert.haml +++ b/lib/generators/backbone/install/templates/alerts/_success_alert.haml @@ -1,4 +1,7 @@ -.alert-message.warning +.alert-message.success.block-message %a.close{:href =>"#"} x + + {{each messages}} %p - %strong Ocurrio un super success + %strong ${message} + {{/each}} diff --git a/lib/generators/backbone/install/templates/alerts/_warning_alert.haml b/lib/generators/backbone/install/templates/alerts/_warning_alert.haml index 33371c4..c421a22 100644 --- a/lib/generators/backbone/install/templates/alerts/_warning_alert.haml +++ b/lib/generators/backbone/install/templates/alerts/_warning_alert.haml @@ -1,4 +1,7 @@ -.alert-message.warning +.alert-message.warning.block-message %a.close{:href =>"#"} x + + {{each messages}} %p - %strong Ocurrio un super warning + %strong ${message} + {{/each}} From 2c87d6b74b7989b951ea168b983af897053e6450 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 8 Dec 2011 15:56:24 -0600 Subject: [PATCH 59/78] Added BaseRouter --- .../backbone/install/install_generator.rb | 4 ++ .../backbone/install/templates/app.coffee | 2 + .../install/templates/base_router.coffee | 56 +++++++++++++++++++ .../backbone/scaffold/templates/router.coffee | 28 ++++------ 4 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 lib/generators/backbone/install/templates/base_router.coffee diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index dc84055..1f33077 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -108,6 +108,10 @@ def create_config_files template "config/string.coffee", "app/assets/javascripts/backbone/config/string.js.coffee" end + def create_base_router + template "base_router.coffee", "app/assets/javascripts/backbone/routers/base_router.js.coffee" + end + end end end diff --git a/lib/generators/backbone/install/templates/app.coffee b/lib/generators/backbone/install/templates/app.coffee index c420756..ad15393 100644 --- a/lib/generators/backbone/install/templates/app.coffee +++ b/lib/generators/backbone/install/templates/app.coffee @@ -7,8 +7,10 @@ #= require_tree ./models #= require ./views/base_view #= require_tree ./views +#= require ./routers/base_router #= require_tree ./routers + window.<%= js_app_name %> = Models: {} Collections: {} diff --git a/lib/generators/backbone/install/templates/base_router.coffee b/lib/generators/backbone/install/templates/base_router.coffee new file mode 100644 index 0000000..baa580c --- /dev/null +++ b/lib/generators/backbone/install/templates/base_router.coffee @@ -0,0 +1,56 @@ +class <%= js_app_name %>.Routers.BaseRouter extends Backbone.Router + + # Manually bind a single named route to a callback. For example: + # + # @route('search/:query/p:num', 'search', (query, num) -> + # ... + # + + route : (route, name, callback) -> + Backbone.history || (Backbone.history = new Backbone.History) + + route = @._routeToRegExp(route) if (!_.isRegExp(route)) + + Backbone.history.route(route, _.bind( + (fragment) -> + args = this._extractParameters(route, fragment) + + @removeViews(name) + @resetModelsWithoutSaving() + @beforeFilter() + + callback.apply(this, args) + + @trigger.apply(this, ['route:' + name].concat(args)) + + this) + ) + + beforeFilter: -> + + removeViews: (name) -> + @["#{name}_view"].remove() if @["#{name}_view"]? # index_view + @["#{name}View"].remove() if @["#{name}View"]? # customNameView + + resetModelsWithoutSaving: () -> + _.each(@_editedModels, (model) -> + model.resetToOriginValues() + ) + @_editedModels = [] + + resourceNotFound: -> + @flash "warning", @t("errors.not_found") + window.location.hash = "/index" + + # I18n support + t: (route = "") -> + Modules.I18n.t route + + # Falsh Messages + flash: (type, messages = "") -> + if _.include <%= js_app_name %>.Config.flashes, type + if _.isString messages + messages = {messages: [{message: messages}]} + + flashTemplate = "render_#{type}".toCamelize("lower") + <%= js_app_name %>.Helpers[flashTemplate]? messages diff --git a/lib/generators/backbone/scaffold/templates/router.coffee b/lib/generators/backbone/scaffold/templates/router.coffee index d6194f0..c200ac8 100644 --- a/lib/generators/backbone/scaffold/templates/router.coffee +++ b/lib/generators/backbone/scaffold/templates/router.coffee @@ -1,4 +1,4 @@ -class <%= router_namespace %>Router extends Backbone.Router +class <%= router_namespace %>Router extends <%= js_app_name %>.Routers.BaseRouter initialize: (options) -> @<%= plural_model_name %> = new <%= collection_namespace %>Collection() @@ -15,33 +15,29 @@ class <%= router_namespace %>Router extends Backbone.Router ".*" : "index" new<%= class_name %>: -> - @resetModelsWithoutSaving() @new_view = new <%= "#{view_namespace}.NewView(collection: @#{plural_model_name})" %> $("#<%= plural_name %>").html(@new_view.render().el) index: -> - @resetModelsWithoutSaving() - @index_view.remove() if @index_view? @index_view = new <%= "#{view_namespace}.IndexView(#{plural_model_name}: @#{plural_model_name})" %> $("#<%= plural_name %>").html(@index_view.render().el) show: (id) -> - @resetModelsWithoutSaving() <%= singular_name %> = @<%= plural_model_name %>.get(id) - @show_view = new <%= "#{view_namespace}.ShowView(model: #{singular_name})" %> - $("#<%= plural_name %>").html(@show_view.render().el) + if <%= singular_name %>? + <%= singular_name %>.setAllValues() + + @show_view = new <%= "#{view_namespace}.ShowView(model: #{singular_name})" %> + $("#<%= plural_name %>").html(@show_view.render().el) + else @resourceNotFound() edit: (id) -> - @resetModelsWithoutSaving() <%= singular_name %> = @<%= plural_model_name %>.get(id) - @edit_view.remove() if @edit_view? - @edit_view = new <%= "#{view_namespace}.EditView(model: #{singular_name})" %> - $("#<%= plural_name %>").html(@edit_view.render().el) + if <%= singular_name %>? + <%= singular_name %>.setAllValues() - resetModelsWithoutSaving: () -> - _.each(@_editedModels, (model) -> - model.resetToOriginValues() - ) - @_editedModels = [] + @edit_view = new <%= "#{view_namespace}.EditView(model: #{singular_name})" %> + $("#<%= plural_name %>").html(@edit_view.render().el) + else @resourceNotFound() From c8f58effc75ceff471381428cc07f52215a76acd Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 8 Dec 2011 16:00:12 -0600 Subject: [PATCH 60/78] Added collection_scopes method --- .../install/templates/backbone_responses.rb | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/lib/generators/backbone/install/templates/backbone_responses.rb b/lib/generators/backbone/install/templates/backbone_responses.rb index 7fdcde0..7d7114e 100644 --- a/lib/generators/backbone/install/templates/backbone_responses.rb +++ b/lib/generators/backbone/install/templates/backbone_responses.rb @@ -50,12 +50,7 @@ def show protected def collection - if paginate? - resources = collection_scopes.paginate( - :page => (params[:page] || 1), :per_page => resources_per_page) - else - resources = collection_scopes.all - end + resources = collection_scopes.scoped instance_variable_set("@#{controller_name}" , resources) end @@ -75,29 +70,8 @@ def resource_public_attributes end def collection_public_attributes - model = end_of_association_chain - resources = collection - - if model.respond_to?(:acts_as_api?) and model.acts_as_api? and model.respond_to?(:"api_accessible_#{api_collection_template}") - allowed_keys = resources.collect{|o| o.as_api_response(:"#{api_collection_template}")} - else - allowed_keys = resources - end - if paginate? - per_page = resources.per_page - total_entries = resources.total_entries - total_pages = (total_entries.to_f / per_page.to_f).ceil - - resources_with_pagination = {} - resources_with_pagination[:resources] = allowed_keys - resources_with_pagination[:pagination] = { - :current_page => resources.current_page, - :per_page => per_page, - :total_entries => total_entries, - :total_pages => total_pages - } - instance_variable_set("@#{controller_name}" , resources_with_pagination) + instance_variable_set("@#{controller_name}" , resources_with_pagination(collection)) else instance_variable_set("@#{controller_name}" , allowed_keys) end @@ -105,8 +79,42 @@ def collection_public_attributes end + def resources_with_pagination(*args) + model = end_of_association_chain + resources = args.first.paginate(:page => (params[:page] || 1), :per_page => resources_per_page) + + options = args.second || {} + template = options[:template] || api_collection_template + path = options[:path] || "" + query_params = options[:params] || {} + + query_params.delete(:page) + + if model.respond_to?(:acts_as_api?) and model.acts_as_api? and model.respond_to?(:"api_accessible_#{template}") + allowed_keys = resources.as_api_response(:"#{template}") + else + allowed_keys = resources + end + + per_page = resources.per_page + total_entries = resources.total_entries + total_pages = (total_entries.to_f / per_page.to_f).ceil + + { + :resources => allowed_keys, + :pagination => { + :current_page => resources.current_page, + :per_page => per_page, + :total_entries => total_entries, + :total_pages => total_pages, + :params => query_params, + :path => path + } + } + end + def api_collection_template - "public" + params[:api_template] || "list" end def api_resource_template From f14379232b91263daf37e29d516d0905b77d8738 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 8 Dec 2011 16:03:20 -0600 Subject: [PATCH 61/78] Added setAllValues method --- .../install/templates/base_model.coffee | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_model.coffee b/lib/generators/backbone/install/templates/base_model.coffee index 6ea5ec5..3fa3c21 100644 --- a/lib/generators/backbone/install/templates/base_model.coffee +++ b/lib/generators/backbone/install/templates/base_model.coffee @@ -44,7 +44,18 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model return value # fall back to the default backbone behavior - return Backbone.Model.prototype.get.call(this, key) + super(key) + + setAllValues: -> + resettable = if _.isFunction(@isResettable) then @isResettable() else @isResettable + if resettable is true and @allValuesSeted is false + data = <%= js_app_name %>.Helpers.jsonData @url() + + if data? + @resetRelations data + @allValuesSeted = true + + allValuesSeted: false toJSON: ( includeRelations = false, includeCalculated = false ) -> @@ -148,11 +159,8 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model if newValue = @get(relation.foreignKey) if newValue isnt @[key].get("id") url = "/#{relation.route}/#{newValue}" - <%= js_app_name %>.Helpers.jsonCallback( - url - (data) => @[key].set(data, {silent: true}) if data? - {api_template: "base"} # params - ) + data = <%= js_app_name %>.Helpers.jsonData url, api_template: "base" + @[key].set(data, {silent: true}) if data? # clear attributes if foreignKey is null else @[key].clear silent: true @@ -190,11 +198,17 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model relation - resetRelations: (attributes) -> + resetRelations: (data) -> + # Self Attributes + _.each(data, (value, key) => + if !@belongsTo[key]? or !@hasMany[key]? + @attributes[key] = data[key] + ) + # belongsTo _.each(@belongsTo, (relation, key) => - values = attributes[key] + values = data[key] relation = @buildBelonsToRelation(relation, key) if values? and ( relation.isNested is true or relation.resettable is true) @[key] = new <%= js_app_name %>.Models[relation.model] values @@ -202,7 +216,7 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model # hasMany _.each(@hasMany, (relation, key) => - values = attributes[key] + values = data[key] @[key].url = "#{@collectionRoute}/#{@get('id')}/#{key}" unless @isNew() @[key].reset values if values? ) @@ -210,7 +224,7 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model validates: (attrs, validates = {}) -> resultMessage = {} - messages = Modules.I18n.hash().errorsMessages + messages = Modules.I18n.hash().errorsMessages # Each for attributes of the model _.each(attrs, (attrValue, attrKey) => @@ -309,6 +323,11 @@ class <%= js_app_name %>.Models.BaseModel extends Backbone.Model removeWhenSaving: [] + isResettable: -> + _.isEmpty(@hasMany) is false + + resettableAttributes: [] + # Callbacks afterSave: {} From ce7d65b46e62b6df6158775b217cc329bca0660a Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 8 Dec 2011 16:05:45 -0600 Subject: [PATCH 62/78] Added functions for remote forms and ajax request --- .../install/templates/base_view.coffee | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index 13c3574..3f372d7 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -49,7 +49,6 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View e.stopPropagation() form = $(e.currentTarget) - return false unless @allowAction(form) options = _.extend( success: (model) => @@ -60,10 +59,12 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options) if @model.isValid() is true + return false unless @allowAction(form) @collection.create(@model, success: (model, jqXHR) => window.router._editedModels = [] @model.resetRelations(jqXHR) + @model.allValuesSeted = true model.trigger("afterSave", model, jqXHR) options.success(model, jqXHR) error: options.error @@ -75,7 +76,6 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View e.stopPropagation() form = $(e.currentTarget) - return false unless @allowAction(form) options = _.extend( success : (model) => @@ -86,16 +86,23 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View options) if @model.isValid() is true + return false unless @allowAction(form) @model.save(null, success: (model, jqXHR) => window.router._editedModels = [] @model.resetRelations(jqXHR) + @model.allValuesSeted = true model.trigger("afterSave", model, jqXHR) options.success(model, jqXHR) error: options.error ) else @renderErrors(@model, @model.errors) + # Progress bar + # ========================================================== + renderProgress: (schedule_id, callback) -> + <%= js_app_name %>.Helpers.renderProgress(schedule_id, callback) + # Errors # ========================================================== renderErrors: (model, errors) -> @@ -126,17 +133,25 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View ) renderPagination: (collection) -> + # Clear Pagination Container + @$("#pagination-container").html "" + pagination = collection.pagination || {} if pagination.total_pages > 1 - pagination.resources_path = collection.url + pagination.resources_path = pagination.path || collection.url + pagination.params = $.param(pagination.params) pagination.pages = [] if (pagination.current_page > 1) - pagination.paginatePrev = (pagination.current_page - 1) + prevNumber = (pagination.current_page - 1) + pagination.paginatePrev = "#{pagination.resources_path}?page=#{prevNumber}" + pagination.paginatePrev += "&#{pagination.params}" unless (_.isEmpty pagination.params) if (pagination.current_page < pagination.total_pages) - pagination.paginateNext = (pagination.current_page + 1) + nextNumber = (pagination.current_page + 1) + pagination.paginateNext = "#{pagination.resources_path}?page=#{nextNumber}" + pagination.paginateNext += "&#{pagination.params}" unless (_.isEmpty pagination.params) # builder pages for number in [1..pagination.total_pages] @@ -144,6 +159,7 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View page.liKlass = "active" if pagination.current_page is number page.text = number page.path = "#{pagination.resources_path}?page=#{number}" + page.path += "&#{pagination.params}" unless (_.isEmpty pagination.params) pagination.pages.push(page) @$("#pagination-container").html( @@ -169,3 +185,27 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View flashTemplate = "render_#{type}".toCamelize("lower") <%= js_app_name %>.Helpers[flashTemplate]? messages + # Do an ajax request + doAjax: (settings = {}) -> + <%= js_app_name %>.Helpers.ajax(settings) + + # Remote Forms + remoteForm: (e, settings = {}) -> + e.preventDefault() + e.stopPropagation() + + form = $(e.currentTarget) + + url = form.prop("action") + + if url? + return false unless @allowAction(form) + type = form.prop("method") || "GET" + data = form.serializeArray() || {} + + if form.prop("enctype") is "multipart/form-data" + files = $(":file", form) + settings = _.extend { files: files, iframe: true, processData: false }, settings + + settings = _.extend { url: url, type: type, data: data }, settings + @doAjax settings From 28dfabc6bbf0e33433b0106d0e677da31c9a7599 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 8 Dec 2011 16:09:30 -0600 Subject: [PATCH 63/78] Added support for progress bar jquery-ui --- .../backbone/install/templates/helpers.coffee | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/generators/backbone/install/templates/helpers.coffee b/lib/generators/backbone/install/templates/helpers.coffee index ce3a173..57bf808 100644 --- a/lib/generators/backbone/install/templates/helpers.coffee +++ b/lib/generators/backbone/install/templates/helpers.coffee @@ -49,3 +49,20 @@ renderInfo: (data) -> $("#alerts_container").html( $("#backboneInfoAlert").tmpl(data) ) + + renderProgress: (schedule_id, callback) -> + if schedule_id? + $(".alert-message").remove() + progress = $("#progress_bar") + + progress.progressbar + value: 0 + complete: -> + clearInterval interval + callback?() + + interval = setInterval -> + $.getJSON "schedules/#{schedule_id}", (data) -> + count = (data.progress * 100) / data.total + progress.progressbar "option", "value", count + , 1500 From 878456784b8efff54a01d0d189a79fc82f83b653 Mon Sep 17 00:00:00 2001 From: Jairo Vazquez Date: Thu, 8 Dec 2011 18:19:51 -0600 Subject: [PATCH 64/78] Added jquery.iframe-transport plugin --- .gitignore | 3 +- .../backbone/install/install_generator.rb | 1 + .../install/templates/base_view.coffee | 9 +- .../javascripts/jquery.iframe-transport.js | 221 ++++++++++++++++++ 4 files changed, 228 insertions(+), 6 deletions(-) create mode 100755 vendor/assets/javascripts/jquery.iframe-transport.js diff --git a/.gitignore b/.gitignore index 57c7c04..5d4828b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ test/dummy/.sass-cache/ test/tmp/**/* .idea/ .rvmrc - +.DS_Store +*.orig diff --git a/lib/generators/backbone/install/install_generator.rb b/lib/generators/backbone/install/install_generator.rb index 1f33077..aae712f 100644 --- a/lib/generators/backbone/install/install_generator.rb +++ b/lib/generators/backbone/install/install_generator.rb @@ -16,6 +16,7 @@ def inject_backbone inject_into_file "app/assets/javascripts/application.js", :before => "//= require_tree" do [ "//= require jquery.tmpl", + "//= require jquery.iframe-transport", "//= require underscore", "//= require backbone", "//= require backbone_rails_sync", diff --git a/lib/generators/backbone/install/templates/base_view.coffee b/lib/generators/backbone/install/templates/base_view.coffee index 3f372d7..8a47b20 100644 --- a/lib/generators/backbone/install/templates/base_view.coffee +++ b/lib/generators/backbone/install/templates/base_view.coffee @@ -195,16 +195,15 @@ class <%= js_app_name %>.Views.BaseView extends Backbone.View e.stopPropagation() form = $(e.currentTarget) - url = form.prop("action") if url? return false unless @allowAction(form) - type = form.prop("method") || "GET" - data = form.serializeArray() || {} + type = form.prop("method") || "GET" + data = form.serializeArray() || {} + files = $(":file", form) - if form.prop("enctype") is "multipart/form-data" - files = $(":file", form) + if form.prop("enctype") is "multipart/form-data" and files.length > 0 settings = _.extend { files: files, iframe: true, processData: false }, settings settings = _.extend { url: url, type: type, data: data }, settings diff --git a/vendor/assets/javascripts/jquery.iframe-transport.js b/vendor/assets/javascripts/jquery.iframe-transport.js new file mode 100755 index 0000000..211f568 --- /dev/null +++ b/vendor/assets/javascripts/jquery.iframe-transport.js @@ -0,0 +1,221 @@ +// This [jQuery](http://jquery.com/) plugin implements an `