Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

alpha

  • Loading branch information...
commit e0f0ab06848d455bcba159df5e2d1017c1687b96 1 parent 1053925
Alexander Gräfenstein authored
Showing with 910 additions and 0 deletions.
  1. BIN  .DS_Store
  2. +20 −0 LICENSE
  3. +17 −0 README.rdoc
  4. +53 −0 Rakefile
  5. +1 −0  VERSION
  6. BIN  app/public/images/railsgrid/add.png
  7. BIN  app/public/images/railsgrid/clear.png
  8. BIN  app/public/images/railsgrid/ddn.png
  9. BIN  app/public/images/railsgrid/dn.png
  10. BIN  app/public/images/railsgrid/first.png
  11. BIN  app/public/images/railsgrid/last.png
  12. BIN  app/public/images/railsgrid/loading.gif
  13. BIN  app/public/images/railsgrid/magnifier.png
  14. BIN  app/public/images/railsgrid/next.png
  15. BIN  app/public/images/railsgrid/prev.png
  16. BIN  app/public/images/railsgrid/reload.png
  17. BIN  app/public/images/railsgrid/th_bg.png
  18. BIN  app/public/images/railsgrid/up.png
  19. BIN  app/public/images/railsgrid/uup.png
  20. +221 −0 app/public/javascripts/railsgrid.js
  21. +148 −0 app/public/stylesheets/railsgrid.css
  22. 0  README → app/views/railsgrid/_cells.html.haml
  23. +34 −0 app/views/railsgrid/_controls.html.haml
  24. +30 −0 app/views/railsgrid/_frame.html.haml
  25. +7 −0 config/locales/railsgrid.de.yml
  26. +7 −0 config/locales/railsgrid.en.yml
  27. +36 −0 lib/column.rb
  28. +29 −0 lib/railsgrid.rb
  29. +19 −0 lib/result.rb
  30. +123 −0 lib/table.rb
  31. +50 −0 lib/table_helper.rb
  32. +59 −0 lib/tasks/railsgrid.rake
  33. 0  lib/version.rb
  34. BIN  pkg/railsgrid-0.1.0.gem
  35. +39 −0 railsgrid.gemspec
  36. +10 −0 test/helper.rb
  37. +7 −0 test/test_railsgrid.rb
View
BIN  .DS_Store
Binary file not shown
View
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 Alexander Gräfenstein
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
17 README.rdoc
@@ -0,0 +1,17 @@
+= railsgrid
+
+Description goes here.
+
+== Note on Patches/Pull Requests
+
+* Fork the project.
+* Make your feature addition or bug fix.
+* Add tests for it. This is important so I don't break it in a
+ future version unintentionally.
+* Commit, do not mess with rakefile, version, or history.
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
+* Send me a pull request. Bonus points for topic branches.
+
+== Copyright
+
+Copyright (c) 2010 Alexander Gräfenstein. See LICENSE for details.
View
53 Rakefile
@@ -0,0 +1,53 @@
+require 'rubygems'
+require 'rake'
+
+begin
+ require 'jeweler'
+ Jeweler::Tasks.new do |gem|
+ gem.name = "railsgrid"
+ gem.summary = %Q{Tables in rails}
+ gem.description = %Q{Easy tables in rails}
+ gem.email = "giniedp@online.de"
+ gem.homepage = "http://github.com/giniedp/railsgrid"
+ gem.authors = ["Alexander Gräfenstein"]
+ # gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+ end
+ Jeweler::GemcutterTasks.new
+rescue LoadError
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
+end
+
+require 'rake/testtask'
+Rake::TestTask.new(:test) do |test|
+ test.libs << 'lib' << 'test'
+ test.pattern = 'test/**/test_*.rb'
+ test.verbose = true
+end
+
+begin
+ require 'rcov/rcovtask'
+ Rcov::RcovTask.new do |test|
+ test.libs << 'test'
+ test.pattern = 'test/**/test_*.rb'
+ test.verbose = true
+ end
+rescue LoadError
+ task :rcov do
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
+ end
+end
+
+task :test => :check_dependencies
+
+task :default => :test
+
+require 'rake/rdoctask'
+Rake::RDocTask.new do |rdoc|
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
+
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = "railsgrid #{version}"
+ rdoc.rdoc_files.include('README*')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
View
1  VERSION
@@ -0,0 +1 @@
+0.1.0
View
BIN  app/public/images/railsgrid/add.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/clear.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/ddn.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/dn.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/first.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/last.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/loading.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/magnifier.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/next.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/prev.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/reload.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/th_bg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/up.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/public/images/railsgrid/uup.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
221 app/public/javascripts/railsgrid.js
@@ -0,0 +1,221 @@
+(function($, undefined) {
+
+ $.fn.railsgrid = function(method) {
+ if ( methods[method] ) {
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
+ } else if (typeof(method) === 'object' || !method) {
+ return methods.init.apply(this, arguments);
+ } else {
+ $.error( 'Method ' + method + ' does not exist on jQuery.railsgrid' );
+ }
+ };
+
+ var methods = {
+ init : function(options){
+ var settings = {
+ url : "/",
+ name : "",
+ query : {
+ pagination : { page : 0, per_page : 20 },
+ conditions : {},
+ order : {}
+ },
+ searchFadeTime : 250,
+ searchFadeOpac : 0.5,
+ queries : 0
+ }
+ options = (options || {});
+ $.extend(settings, options);
+
+ return this.each(function(){
+ var $this = $(this);
+ var data = $this.data('railsgrid');
+
+ if (!data){
+ // initialize railsgrid
+
+ // set data
+ $this.data('railsgrid', settings);
+
+ // search attribute changed/focused
+ $this.find(".js-attribute").bind("change.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('newSearch');
+ return false;
+ }).bind("focus.railsgrid", function(){
+ $(this).select();
+ return false;
+ });
+
+ // search attribute changed/focused
+ $this.find(".js-page").bind("change.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('page', $(this).val());
+ return false;
+ }).bind("focus.railsgrid", function(){
+ $(this).select();
+ return false;
+ });
+
+ // previous page click
+ $this.find(".js-previous").bind("click.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('previousPage');
+ return false;
+ });
+
+ // next page click
+ $this.find(".js-next").bind("click.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('nextPage');
+ return false;
+ });
+
+ // reload click
+ $this.find(".js-reload").bind("click.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('reloadPage');
+ return false;
+ });
+
+ // clear click
+ $this.find(".js-clear").bind("click.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('clearSearch');
+ return false;
+ });
+
+ // clear click
+ $this.find(".js-per-page").bind("change.railsgrid", function(){
+ $(this).parents(".js-railsgrid").railsgrid('perPage', $(this).val());
+ return false;
+ });
+ } else {
+ $.extend(data, options);
+ }
+ });
+ },
+ destroy : function(){
+ return this.each(function(){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.unbind('.railsgrid');
+ $this.removeData('railsgrid');
+ });
+ },
+ setupConditions : function(){
+ var $this = $(this);
+ var data = $this.data('railsgrid');
+
+ data.query.conditions = {};
+ $(this).find(".js-attribute").each(function(){
+ data.query.conditions[$(this).attr("name")] = $(this).val();
+ });
+ },
+ setupPagination : function(page, perPage){
+ var $this = $(this);
+ var data = $this.data('railsgrid');
+
+ data.query.pagination = { page : 0, per_page : 20 };
+ if(!isNaN(Number(page)) && Number(page) >= 0){
+ data.query.pagination.page = page;
+ }
+ if (!isNaN(Number(perPage)) && Number(perPage) > 0){
+ data.query.pagination.per_page = perPage;
+ }
+ },
+ order : function(){
+ return "";
+ },
+ search : function(){
+ var $this = $(this);
+ var $content = $this.find(".js-tablewrapper");
+ var $control = $this.find(".js-tablecontrol");
+ var data = $this.data('railsgrid');
+ data.queries += 1;
+
+ $control.find(".js-reload").addClass("loading");
+ $this.fadeTo(data.searchFadeTime, data.searchFadeOpac);
+
+ $.ajax({
+ type : "GET",
+ url : data.url,
+ data : data.query,
+ dataType : "html",
+ success : function(result){
+ data.queries -= 1;
+ if(data.queries == 0){
+ $content.find(".js-row").detach();
+ $content.find("table").append($(result).find(".js-row"));
+ $control.find(".js-per-page").val(data.query.pagination.per_page);
+ $control.find(".js-page").val(Number(data.query.pagination.page) + 1);
+
+ total = (Number($(result).find(".js-page-total").text()));
+ totalPages = total / data.query.pagination.per_page
+ totalPages = (totalPages | 0) + 1;
+
+ $control.find(".js-page-total").text(totalPages);
+
+ $this.fadeTo(data.searchFadeTime, 1.0, function(){
+ $control.find(".js-reload").removeClass("loading");
+ });
+ }
+ },
+ error : function(){
+ data.queries -= 1;
+ if(data.queries == 0){
+ $content.find(".js-row").detach();
+ $this.fadeTo(data.searchFadeTime, 1.0, function(){
+ $control.find(".js-reload").removeClass("loading");
+ });
+ }
+ }
+ });
+ },
+ nextPage : function(){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.railsgrid("setupPagination", data.query.pagination.page + 1, data.query.pagination.per_page);
+ $this.railsgrid("search");
+ },
+ previousPage : function(){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.railsgrid("setupPagination", data.query.pagination.page - 1, data.query.pagination.per_page);
+ $this.railsgrid("search");
+ },
+ perPage : function(perPage){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.railsgrid("setupPagination", 0, perPage);
+ $this.railsgrid("search");
+ },
+ page : function(page){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.railsgrid("setupPagination", Number(page) - 1, data.query.pagination.per_page);
+ $this.railsgrid("search");
+ },
+ reloadPage : function(){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.railsgrid("setupPagination", data.query.pagination.page, data.query.pagination.per_page);
+ $this.railsgrid("setupConditions");
+ $this.railsgrid("search");
+ },
+ newSearch : function(){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.railsgrid("setupPagination", 0, data.query.pagination.per_page);
+ $this.railsgrid("setupConditions");
+ $this.railsgrid("search");
+ },
+ clearSearch : function(){
+ var $this = $(this);
+ data = $this.data('railsgrid');
+ $this.find(".js-attribute").each(function(){
+ $(this).val("");
+ });
+ $this.railsgrid("setupPagination", 0, data.query.pagination.per_page);
+ $this.railsgrid("setupConditions");
+ $this.railsgrid("search");
+ },
+ action : function(name, value){
+ $(this).trigger("action_" + name, value);
+ }
+ };
+})(jQuery);
View
148 app/public/stylesheets/railsgrid.css
@@ -0,0 +1,148 @@
+/* line 2, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper {
+ clear: left;
+ overflow: auto;
+ margin: 0px;
+ min-height: 60px;
+ border-left: 1px solid #cccccc;
+ border-right: 1px solid #cccccc;
+}
+/* line 10, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table {
+ width: 100%;
+ border-spacing: 0px;
+}
+/* line 14, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table th {
+ background: #d7d7d7;
+ text-align: left;
+ padding: 5px;
+ padding-left: 10px;
+ padding-right: 10px;
+ border-right: 1px solid #cccccc;
+ font-weight: bold;
+}
+/* line 24, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr td {
+ padding: 4px 10px 4px 10px;
+ border-right: 1px solid #cccccc;
+ background: none repeat scroll 0 0 #F7F7F7;
+}
+/* line 28, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr td img {
+ vertical-align: bottom;
+}
+/* line 30, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr .sed {
+ text-align: center;
+}
+/* line 32, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr .sed a {
+ display: none;
+}
+/* line 38, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr.js-search td {
+ padding: 4px;
+}
+/* line 41, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr.js-search td input {
+ border: 1px solid #ccc;
+ width: 98%;
+ height: 25px;
+ display: inline;
+ margin: 0px;
+ padding: 0px;
+}
+/* line 52, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr.js-search:hover td {
+ background: none repeat scroll 0 0 #F7F7F7;
+}
+/* line 57, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr:hover td {
+ background: #d5effc;
+}
+/* line 60, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr:hover .sed {
+ text-align: center;
+}
+/* line 63, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid .js-tablewrapper table tr:hover .sed a {
+ display: inline;
+}
+/* line 71, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol.bottom {
+ background: #d7d7d7;
+}
+/* line 74, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol.top {
+ background: #d7d7d7 url("/images/railsgrid/th_bg.png") top repeat-x;
+}
+/* line 77, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol {
+ clear: both;
+ display: block;
+ text-align: center;
+ margin: 0px;
+ padding: 5px;
+}
+/* line 83, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li {
+ list-style: none;
+ display: inline;
+ margin: 0px 2px 0px 2px;
+ padding: 0;
+}
+/* line 88, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li input, .js-railsgrid ul.js-tablecontrol li select {
+ width: 60px !important;
+}
+/* line 92, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button {
+ width: 20px;
+ height: 20px;
+ cursor: pointer;
+}
+/* line 97, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button span {
+ width: 20px;
+ height: 20px;
+}
+/* line 102, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .first {
+ background: url("/images/railsgrid/first.png") no-repeat;
+}
+/* line 105, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .last {
+ background: url("/images/railsgrid/last.png") no-repeat;
+}
+/* line 108, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .js-next {
+ background: url("/images/railsgrid/next.png") no-repeat;
+}
+/* line 111, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .js-previous {
+ background: url("/images/railsgrid/prev.png") no-repeat;
+}
+/* line 114, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .js-reload {
+ background: url("/images/railsgrid/reload.png") no-repeat;
+}
+/* line 117, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .js-clear {
+ background: url("/images/railsgrid/clear.png") no-repeat;
+}
+/* line 120, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .loading {
+ background: url("/images/railsgrid/loading.gif") no-repeat;
+}
+/* line 123, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.button .new {
+ background: url("/images/railsgrid/add.png") no-repeat;
+}
+/* line 128, ../../../app/stylesheets/_railsgrid.scss */
+.js-railsgrid ul.js-tablecontrol li.separator {
+ border-left: 1px solid #CCCCCC;
+ border-right: 1px solid #FFFFFF;
+ height: 22px;
+ margin: 1px;
+}
View
0  README → app/views/railsgrid/_cells.html.haml
File renamed without changes
View
34 app/views/railsgrid/_controls.html.haml
@@ -0,0 +1,34 @@
+%ul.js-tablecontrol{ :class => html_class }
+ %li
+ %span
+ = I18n.t("railsgrid.pagination.per_page", :default => "Results per Page")
+ = select(:per_page, :to_i, railsgrid_page_opts[:selection], { :selected => railsgrid_page_opts[:selected] }, :class => "js-per-page")
+ %li.separator
+ %li.button
+ %span.js-previous
+ &nbsp;&nbsp;&nbsp;
+ %li
+ %span
+ = I18n.t("railsgrid.pagination.page", :default => "Page")
+ %input.js-page{ :type => "text", :value => "1"}
+ %span
+ = I18n.t("railsgrid.pagination.of", :default => "of")
+ %span.js-page-total
+ = railsgrid.result and railsgrid.result.total
+ %li.button
+ %span.js-next
+ &nbsp;&nbsp;&nbsp;
+ %li.separator
+ %li.button
+ %span.js-reload
+ &nbsp;&nbsp;&nbsp;
+ %li.button
+ %span.js-clear
+ &nbsp;&nbsp;&nbsp;
+ %li.separator
+ /- if railsgrid.toolbars[:default]
+ / - railsgrid.toolbars[:default].each do |k, v|
+ / %li.button
+ / %span{ :class => k, :onclick => "$(this).parents('.js-railsgrid').railsgrid('action', '#{k}', '#{v}'); return false;" }
+ / &nbsp;&nbsp;&nbsp;
+ /
View
30 app/views/railsgrid/_frame.html.haml
@@ -0,0 +1,30 @@
+.js-railsgrid{ :class => railsgrid.css_selector }
+ = render :file => Railsgrid::Table.control_template, :locals => { :railsgrid => railsgrid, :html_class => "top" }
+ .js-tablewrapper
+ %table
+ %tr.js-header
+ - railsgrid.columns.each do |column|
+ %th{ :class => column.css_name}
+ = column.human_name
+
+ %tr.js-search
+ - railsgrid.columns.each do |column|
+ %td{ :class => column.css_name}
+ - if column.searchable
+ %input.js-attribute{ :type => "text", :name => column.column_name, :value => column.search_value }
+
+ - if params[:pagination]
+ - railsgrid_results(railsgrid.name) do |item|
+ %tr.js-row
+ - railsgrid_result_values(railsgrid.name, item) do |value|
+ %td
+ = value
+
+ = render :file => Railsgrid::Table.control_template, :locals => { :railsgrid => railsgrid, :html_class => "bottom" }
+
+:javascript
+ $(function(){
+ $(".js-railsgrid.#{railsgrid.css_selector}").railsgrid({ url : '#{railsgrid.url}'});
+ $(".js-railsgrid.#{railsgrid.css_selector}").railsgrid("reloadPage");
+ });
+
View
7 config/locales/railsgrid.de.yml
@@ -0,0 +1,7 @@
+de:
+ railsgrid:
+ pagination:
+ per_page: 'Ergebnisse pro Seite:'
+ page: 'Seite'
+ of: 'von'
+ results: 'Ergebnisse'
View
7 config/locales/railsgrid.en.yml
@@ -0,0 +1,7 @@
+en:
+ railsgrid:
+ pagination:
+ per_page: 'Results per Page:'
+ page: 'Page'
+ of: 'of'
+ results: 'Results'
View
36 lib/column.rb
@@ -0,0 +1,36 @@
+module Railsgrid
+ class Column
+ attr_accessor :column_type, :column_name, :table
+ attr_accessor :model_class, :model_classname, :css_name, :human_name, :table_name, :searchable, :search_value
+
+ def initialize column_type, column_name, table
+ unless %(attribute method cell).include? column_type.to_s
+ raise "column_type must be one of 'attribute', 'method' or 'cell' but is #{column_type}"
+ end
+ # split columnname e.g. "foo[bar][attribute]" => ["foo", "bar", "attribute"]
+ column_name_split = column_name.split(/\[|\]/)
+
+ self.column_type = column_type.to_sym
+ self.column_name = column_name
+ self.css_name = column_name_split.last
+ self.table = table
+
+ self.model_classname = column_name_split[-2] # ["foo", "bar", "attribute"] => classname is "bar"
+ self.model_class = self.model_classname.camelize.constantize
+ self.searchable = %(attribute).include? column_type.to_s
+
+ temp = column_name_split.last
+ self.human_name = model_class.human_attribute_name(temp, :default => temp.camelize)
+ self.human_name = I18n.t("railsgrid.tables.#{column_name_split.join('.')}", :default => human_name)
+
+ self.search_value = ""
+
+ if self.model_class < ActiveRecord::Base
+ self.table_name = self.model_class.table_name
+ else
+ self.table_name = self.model_class.name.underscore.pluralize
+ end
+ end
+
+ end
+end
View
29 lib/railsgrid.rb
@@ -0,0 +1,29 @@
+%w(table table_helper result column version).each do |file|
+ require File.join(File.dirname(__FILE__), file)
+end
+
+module Railsgrid
+ class Railtie < Rails::Railtie
+ initializer "railsgrid.initialize" do |app|
+
+ # plugin templates
+ plg_frame_tpl = File.join(File.expand_path(File.dirname(__FILE__)), "..", "app", "views", "railsgrid", "_frame.html.haml")
+ plg_contr_tpl = File.join(File.expand_path(File.dirname(__FILE__)), "..", "app", "views", "railsgrid", "_controls.html.haml")
+ plg_cells_tpl = File.join(File.expand_path(File.dirname(__FILE__)), "..", "app", "views", "railsgrid", "_cells.html.haml")
+
+ # custom templates
+ app_frame_tpl = Rails.root.join("app", "views", "railsgrid", "_frame.html.haml")
+ app_contr_tpl = Rails.root.join("app", "views", "railsgrid", "_controls.html.haml")
+ app_cells_tpl = Rails.root.join("app", "views", "railsgrid", "_cells.html.haml")
+
+ # used templates
+ Railsgrid::Table.frame_template = File.exists?(app_frame_tpl) ? app_frame_tpl : plg_frame_tpl
+ Railsgrid::Table.control_template = File.exists?(app_contr_tpl) ? app_contr_tpl : plg_contr_tpl
+ Railsgrid::Table.cells_template = File.exists?(app_cells_tpl) ? app_cells_tpl : plg_cells_tpl
+
+ ActionController::Base.send :include, Railsgrid::TableHelper
+ ActionView::Base.send :include, Railsgrid::TableHelper
+ end
+ end
+end
+
View
19 lib/result.rb
@@ -0,0 +1,19 @@
+module Railsgrid
+ class Result
+ attr_accessor :values, :total
+
+ def initialize table
+ if table.model_class < ActiveRecord::Base
+ self.values = table.model_class.find(:all, table.query)
+ count_query = table.query.reject{ |k, v| [:limit, :offset, :order].include? k }
+ self.total = table.model_class.count(:all, count_query).length
+ elsif table.model_class < ActiveResource::Base
+ self.values = table.model_class.find(:all, :params => table.query)
+ self.total = self.values.delete_at(values.length - 1).total
+ else
+ self.values = []
+ self.total = 0
+ end
+ end
+ end
+end
View
123 lib/table.rb
@@ -0,0 +1,123 @@
+module Railsgrid
+ class Table
+ cattr_accessor :frame_template, :control_template, :cells_template
+ attr_accessor :model_classname, :model_class, :css_selector, :url
+ attr_accessor :columns, :query, :result, :toolbars
+
+ def initialize model_classname
+ self.model_classname = model_classname.to_s
+ self.model_class = model_classname.to_s.camelize.constantize
+ self.css_selector = model_classname.to_s.gsub(/\//, "_") # cant have slashes in css selector
+ self.url = "/" + model_classname.to_s.pluralize
+ self.columns = []
+ self.result = nil
+ self.toolbars = {}
+ self.query = {
+ :joins => nil,
+ :limit => nil,
+ :readonly => false,
+ :select => nil,
+ :group => nil,
+ :offset => nil,
+ :include => nil,
+ :conditions => nil
+ }
+ end
+
+ def name
+ self.model_classname
+ end
+
+ def fields field_type, model_name, names
+ names = [names] unless names.is_a? Array
+ names.each do |name|
+ self.columns << Railsgrid::Column.new(field_type, "#{model_name}[#{name}]", self)
+ end
+ end
+
+ def attributes names, model_name=nil
+ self.fields(:attribute, (model_name or self.model_classname), names)
+ end
+
+ def methods names, model_name=nil
+ self.fields(:method, (model_name or self.model_classname), names)
+ end
+
+ def cells names, model_name=nil
+ self.fields(:cell, (model_name or self.model_classname), names)
+ end
+
+ def button toolbar_name, button_name, button_value
+ # TODO
+ #self.toolbars[toolbar_name] ||= Railsgrid::Toolbar.new(toolbar_name)
+ #self.toolbars[toolbar_name].button(button_name, button_value)
+ end
+
+ def build_query params
+ if params[:pagination]
+ self.query[:limit] = params[:pagination][:per_page].to_i
+ self.query[:offset] = params[:pagination][:page].to_i * self.query[:limit].to_i
+ end
+
+ self.query[:order] = params[:order] if params[:order]
+
+ if params[:conditions]
+ params_conditions = {}
+ flatten_conditions(params[:conditions], params_conditions)
+ params_conditions.reject!{ |k, v| v.blank? }
+
+ conditions = []
+ conditions << params_conditions.map{ |k, v| "#{k} LIKE ?" }.join(" AND ")
+ params_conditions.each{ |k, v| conditions << "%#{v.to_param}%" }
+ self.query[:conditions] = conditions
+ end
+ return self.query
+ end
+
+ def flatten_conditions hash, flat
+ hash.each do |k, v|
+ if v.is_a? Hash
+ flatten_conditions(v, flat)
+ else
+ flat[k] = v
+ end
+ end
+ end
+
+ def run_query params
+ unless self.result
+ self.build_query(params)
+ self.result = Railsgrid::Result.new(self)
+ end
+ self.result
+ end
+
+ def values item, params
+ run_query(params)
+
+ values = []
+ self.columns.each do |col|
+ attribute = col.column_name.split(/\[|\]/)
+ attribute.shift # first is always the model name, skip it
+
+ value = ""
+ if col.column_type == :cell
+ if block_given?
+ value = yield item, col
+ end
+ else
+ instance = item
+ (value = instance.send(attribute.shift)) and (instance = value) while attribute.length > 0
+ end
+
+ values << value
+ end
+
+ values
+ end
+
+ def save
+ self
+ end
+ end
+end
View
50 lib/table_helper.rb
@@ -0,0 +1,50 @@
+require 'ftools'
+
+module Railsgrid
+
+ module TableHelper
+ def railsgrid_for name
+ name = name.classname.underscore if name.is_a?(Class)
+ name = name.to_s
+
+ @railsgrid ||= {}
+ @railsgrid[name] ||= Table.new(name)
+ if block_given?
+ yield @railsgrid[name]
+ end
+ @railsgrid[name].save
+ end
+
+ def railsgrid_results name
+ name = name.to_s
+ if block_given?
+ railsgrid_for(name).run_query(params).values.each do |item| yield item end
+ else
+ railsgrid_for(name).run_query(params).values
+ end
+ end
+
+ def railsgrid_result_values name, item
+ name = name.to_s
+ if block_given?
+ railsgrid_for(name).values(item, params) do |item, col|
+ render :file => Railsgrid::Table.cells_template, :locals => { :item => item, :column => col }
+ end.each do |value| yield value end
+ else
+ railsgrid_for(name).values(item, params)
+ end
+ end
+
+ def railsgrid name
+ render :file => Railsgrid::Table.frame_template, :locals => { :railsgrid => railsgrid_for(name) }
+ end
+
+ def railsgrid_page_opts
+ {
+ :selection => [5, 10, 15, 20, 25, 30, 40, 50],
+ :selected => (params[:pagination] and params[:pagination][:per_page] or 20)
+ }
+ end
+ end
+
+end
View
59 lib/tasks/railsgrid.rake
@@ -0,0 +1,59 @@
+require 'rake'
+require 'net/http'
+require 'uri'
+
+js_source = File.join(File.dirname(__FILE__), '..', '..', 'app', 'public', 'javascripts', 'railsgrid.js')
+js_target = Rails.root.join('public', 'javascripts', 'railsgrid.js')
+js_min = Rails.root.join('public', 'javascripts', 'railsgrid.min.js')
+
+namespace :railsgrid do
+
+ desc "generates needed railsgrid javascript"
+ task :javascript => :environment do
+ puts "- Remove existing railsgrid javascripts"
+ File.delete(js_target) if File.exists?(js_target)
+ File.delete(js_min) if File.exists?(js_min)
+ puts "- Copy railsgrid javascripts"
+ File.open(js_target, 'w') do |f|
+ File.open(js_source, "r") do |file|
+ while (line = file.gets)
+ f.print(line)
+ end
+ end
+ end
+ end
+
+ desc "generates minified railsgrid javascript"
+ task :javascript_min => [:environment, :javascript] do
+
+ lines = []
+ File.open(js_target, 'r') do |f|
+ while (line = f.gets)
+ lines << line
+ end
+ end
+
+ puts "- Minify javascript using 'http://closure-compiler.appspot.com/compile'"
+
+ url = URI.parse('http://closure-compiler.appspot.com/compile')
+ req = Net::HTTP::Post.new(url.path)
+ req.set_form_data({
+ :compilation_level => "SIMPLE_OPTIMIZATIONS",
+ :output_format => "text",
+ :output_info => "compiled_code",
+ :js_code => lines.join("")
+ })
+ res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }
+ case res
+ when Net::HTTPSuccess, Net::HTTPRedirection
+ File.delete(js_target) if File.exists?(js_target)
+ File.delete(js_min) if File.exists?(js_min)
+ File.open(js_min, 'w') do |f|
+ f.print(res.body)
+ end
+ puts "- Javascript minified to #{js_min}"
+ else
+ puts "- Error during google closure request"
+ end
+ end
+end
View
0  lib/version.rb
No changes.
View
BIN  pkg/railsgrid-0.1.0.gem
Binary file not shown
View
39 railsgrid.gemspec
@@ -0,0 +1,39 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE DIRECTLY
+# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{railsgrid}
+ s.version = "0.1.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Alexander Gr\303\244fenstein"]
+ s.date = %q{2010-10-18}
+ s.description = %q{Easy tables in rails}
+ s.email = %q{giniedp@online.de}
+ s.extra_rdoc_files = [
+ "LICENSE",
+ "README.rdoc"
+ ]
+ s.homepage = %q{http://github.com/giniedp/railsgrid}
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.3.6}
+ s.summary = %q{Tables in rails}
+ s.test_files = [
+ "test/helper.rb",
+ "test/test_railsgrid.rb"
+ ]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ else
+ end
+ else
+ end
+end
+
View
10 test/helper.rb
@@ -0,0 +1,10 @@
+require 'rubygems'
+require 'test/unit'
+require 'shoulda'
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+require 'railsgrid'
+
+class Test::Unit::TestCase
+end
View
7 test/test_railsgrid.rb
@@ -0,0 +1,7 @@
+require 'helper'
+
+class TestRailsgrid < Test::Unit::TestCase
+ should "probably rename this file and start testing for real" do
+ flunk "hey buddy, you should probably rename this file and start testing for real"
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.