livelist-rails 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Rakefile CHANGED
@@ -1 +1,3 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new('spec')
@@ -34,8 +34,14 @@ class window.List extends Utilities
34
34
  @fetchingIndicationClass = 'updating'
35
35
  @setOptions(options)
36
36
 
37
- $(@renderTo).bind(@eventName, (event, params) => @fetch(filterPresets: null, page: params?.page))
38
- @fetch(filterPresets: @filters.presets)
37
+ $(@renderTo).bind(@eventName, (event, params) => @fetch(presets: null, page: params?.page))
38
+
39
+ cookie = jQuery.cookie(@filters.cookieName) if jQuery.cookie && @filters.useCookies
40
+ if @filters.useCookies && cookie
41
+ presets = JSON.parse(cookie)
42
+ else
43
+ presets = @filters.presets
44
+ @fetch(presets: presets)
39
45
 
40
46
  displayFetchingIndication: => $(@renderTo).addClass(@fetchingIndicationClass)
41
47
  removeFetchingIndication: => $(@renderTo).removeClass(@fetchingIndicationClass)
@@ -47,14 +53,23 @@ class window.List extends Utilities
47
53
  @filters.filters = _.pluck( @data.filters, 'filter_slug' )
48
54
  @filters.render(@data)
49
55
 
56
+ selections: ->
57
+ filters = {}
58
+ _.each( @filters.filters, (filter) => filters[filter] = @filters.filterSelections( filter ) )
59
+ filters
60
+
50
61
  fetch: (options) ->
51
62
  @fetchRequest.abort() if @fetchRequest
52
63
  searchTerm = @search.searchTerm()
53
64
  params = { filters: {} }
54
- if options.filterPresets?.length > 0
55
- params.filters = options.filterPresets
65
+
66
+ if jQuery.isEmptyObject(options.presets)
67
+ params.filters = @selections()
68
+ if jQuery.cookie && not jQuery.isEmptyObject(params.filters)
69
+ jQuery.cookie(@filters.cookieName, JSON.stringify(params.filters))
56
70
  else
57
- _.each( @filters.filters, (filter) => params.filters[filter] = @filters.filterSelections( filter ) )
71
+ params.filters = options.presets
72
+
58
73
  if searchTerm then params.q = searchTerm
59
74
  if options.page then params.page = options.page
60
75
  @fetchRequest = $.ajax(
@@ -72,10 +87,13 @@ class window.List extends Utilities
72
87
  $(@renderTo).html( Mustache.to_html(@listTemplate, @data, partials) )
73
88
  @removeFetchingIndication()
74
89
 
90
+ window.LiveList.version = '0.0.3'
91
+
75
92
  class window.Filters extends Utilities
76
93
  constructor: (globalOptions, options = {}) ->
77
94
  @setOptions(globalOptions)
78
95
  @filters = if options.presets then _.keys(options.presets) else []
96
+ unless @filters.cookieName then @filters.cookieName = 'livelist_filter_presets'
79
97
  @setOptions(options)
80
98
  $('input.filter_option', @renderTo).live( 'change', => $(@listSelector).trigger(@eventName) )
81
99
  $(@advancedOptionsToggleSelector).click(@handleAdvancedOptionsClick)
@@ -110,7 +128,18 @@ class window.Filters extends Utilities
110
128
  filterValues: (filter) -> _.pluck( $(".#{filter}_filter_input"), 'value' )
111
129
  filterSelections: (filter) -> _.pluck( $("##{filter}_filter_options input.filter_option:checked"), 'value' )
112
130
 
113
- render: (data) -> $(@renderTo).html( Mustache.to_html(@filtersTemplate, data) )
131
+ noFiltersSelected: (data) ->
132
+ _.all( data.filters, (filter) ->
133
+ _.all( filter.options, (option) ->
134
+ not option.selected
135
+ )
136
+ )
137
+
138
+ render: (data) ->
139
+ $(@renderTo).html( Mustache.to_html(@filtersTemplate, data) )
140
+ if @noFiltersSelected(data) && data[@resourceName].length > 0
141
+ $('input[type="checkbox"]', @renderTo).attr('checked', 'checked')
142
+
114
143
 
115
144
  handleAdvancedOptionsClick: (event) =>
116
145
  event.preventDefault()
@@ -51,7 +51,8 @@
51
51
  __extends(List, _super);
52
52
 
53
53
  function List(search, filters, pagination, globalOptions, options) {
54
- var _this = this;
54
+ var cookie, presets,
55
+ _this = this;
55
56
  if (options == null) options = {};
56
57
  this.renderIndex = __bind(this.renderIndex, this);
57
58
  this.removeFetchingIndication = __bind(this.removeFetchingIndication, this);
@@ -68,12 +69,20 @@
68
69
  this.setOptions(options);
69
70
  $(this.renderTo).bind(this.eventName, function(event, params) {
70
71
  return _this.fetch({
71
- filterPresets: null,
72
+ presets: null,
72
73
  page: params != null ? params.page : void 0
73
74
  });
74
75
  });
76
+ if (jQuery.cookie && this.filters.useCookies) {
77
+ cookie = jQuery.cookie(this.filters.cookieName);
78
+ }
79
+ if (this.filters.useCookies && cookie) {
80
+ presets = JSON.parse(cookie);
81
+ } else {
82
+ presets = this.filters.presets;
83
+ }
75
84
  this.fetch({
76
- filterPresets: this.filters.presets
85
+ presets: presets
77
86
  });
78
87
  }
79
88
 
@@ -93,20 +102,30 @@
93
102
  return this.filters.render(this.data);
94
103
  };
95
104
 
96
- List.prototype.fetch = function(options) {
97
- var params, searchTerm, _ref,
105
+ List.prototype.selections = function() {
106
+ var filters,
98
107
  _this = this;
108
+ filters = {};
109
+ _.each(this.filters.filters, function(filter) {
110
+ return filters[filter] = _this.filters.filterSelections(filter);
111
+ });
112
+ return filters;
113
+ };
114
+
115
+ List.prototype.fetch = function(options) {
116
+ var params, searchTerm;
99
117
  if (this.fetchRequest) this.fetchRequest.abort();
100
118
  searchTerm = this.search.searchTerm();
101
119
  params = {
102
120
  filters: {}
103
121
  };
104
- if (((_ref = options.filterPresets) != null ? _ref.length : void 0) > 0) {
105
- params.filters = options.filterPresets;
122
+ if (jQuery.isEmptyObject(options.presets)) {
123
+ params.filters = this.selections();
124
+ if (jQuery.cookie && !jQuery.isEmptyObject(params.filters)) {
125
+ jQuery.cookie(this.filters.cookieName, JSON.stringify(params.filters));
126
+ }
106
127
  } else {
107
- _.each(this.filters.filters, function(filter) {
108
- return params.filters[filter] = _this.filters.filterSelections(filter);
109
- });
128
+ params.filters = options.presets;
110
129
  }
111
130
  if (searchTerm) params.q = searchTerm;
112
131
  if (options.page) params.page = options.page;
@@ -132,6 +151,8 @@
132
151
 
133
152
  })(Utilities);
134
153
 
154
+ window.LiveList.version = '0.0.3';
155
+
135
156
  window.Filters = (function(_super) {
136
157
 
137
158
  __extends(Filters, _super);
@@ -142,6 +163,9 @@
142
163
  this.handleAdvancedOptionsClick = __bind(this.handleAdvancedOptionsClick, this);
143
164
  this.setOptions(globalOptions);
144
165
  this.filters = options.presets ? _.keys(options.presets) : [];
166
+ if (!this.filters.cookieName) {
167
+ this.filters.cookieName = 'livelist_filter_presets';
168
+ }
145
169
  this.setOptions(options);
146
170
  $('input.filter_option', this.renderTo).live('change', function() {
147
171
  return $(_this.listSelector).trigger(_this.eventName);
@@ -159,8 +183,19 @@
159
183
  return _.pluck($("#" + filter + "_filter_options input.filter_option:checked"), 'value');
160
184
  };
161
185
 
186
+ Filters.prototype.noFiltersSelected = function(data) {
187
+ return _.all(data.filters, function(filter) {
188
+ return _.all(filter.options, function(option) {
189
+ return !option.selected;
190
+ });
191
+ });
192
+ };
193
+
162
194
  Filters.prototype.render = function(data) {
163
- return $(this.renderTo).html(Mustache.to_html(this.filtersTemplate, data));
195
+ $(this.renderTo).html(Mustache.to_html(this.filtersTemplate, data));
196
+ if (this.noFiltersSelected(data) && data[this.resourceName].length > 0) {
197
+ return $('input[type="checkbox"]', this.renderTo).attr('checked', 'checked');
198
+ }
164
199
  };
165
200
 
166
201
  Filters.prototype.handleAdvancedOptionsClick = function(event) {
@@ -1 +1 @@
1
- ((function(){var a=function(a,b){return function(){return a.apply(b,arguments)}},b=Object.prototype.hasOwnProperty,c=function(a,c){function e(){this.constructor=a}for(var d in c)b.call(c,d)&&(a[d]=c[d]);return e.prototype=c.prototype,a.prototype=new e,a.__super__=c.prototype,a};window.Utilities=function(){function b(){this.setOptions=a(this.setOptions,this)}return b.prototype.setOptions=function(a,b){var c=this;return b==null&&(b=this),_.each(a,function(a,c){return b[c]=a})},b}(),window.LiveList=function(a){function b(a){this.globalOptions.listSelector=a.list.renderTo,this.globalOptions.eventName="livelist:"+a.global.resourceName,this.globalOptions.urlPrefix="/"+a.global.resourceName,this.setOptions(a.global,this.globalOptions),this.search=new Search(this.globalOptions,a.search),this.filters=new Filters(this.globalOptions,a.filters),this.pagination=new Pagination(this.globalOptions,a.pagination),this.list=new List(this.search,this.filters,this.pagination,this.globalOptions,a.list)}return c(b,a),b.prototype.globalOptions={data:null,resourceName:"items",resourceNameSingular:"item"},b}(Utilities),window.List=function(b){function d(b,c,d,e,f){var g=this;f==null&&(f={}),this.renderIndex=a(this.renderIndex,this),this.removeFetchingIndication=a(this.removeFetchingIndication,this),this.displayFetchingIndication=a(this.displayFetchingIndication,this),this.data=e.data,this.fetchRequest=null,this.search=b,this.filters=c,this.pagination=d,this.setOptions(e),this.listTemplate="{{#"+this.resourceName+"}}{{>"+this.resourceNameSingular+"}}{{/"+this.resourceName+"}}",this.listItemTemplate="<li>{{id}}</li>",this.fetchingIndicationClass="updating",this.setOptions(f),$(this.renderTo).bind(this.eventName,function(a,b){return g.fetch({filterPresets:null,page:b!=null?b.page:void 0})}),this.fetch({filterPresets:this.filters.presets})}return c(d,b),d.prototype.displayFetchingIndication=function(){return $(this.renderTo).addClass(this.fetchingIndicationClass)},d.prototype.removeFetchingIndication=function(){return $(this.renderTo).removeClass(this.fetchingIndicationClass)},d.prototype.renderIndex=function(a,b,c){return this.data=a,this.render(),this.pagination.render(this.data),this.filters.filters=_.pluck(this.data.filters,"filter_slug"),this.filters.render(this.data)},d.prototype.fetch=function(a){var b,c,d,e=this;return this.fetchRequest&&this.fetchRequest.abort(),c=this.search.searchTerm(),b={filters:{}},((d=a.filterPresets)!=null?d.length:void 0)>0?b.filters=a.filterPresets:_.each(this.filters.filters,function(a){return b.filters[a]=e.filters.filterSelections(a)}),c&&(b.q=c),a.page&&(b.page=a.page),this.fetchRequest=$.ajax({url:this.urlPrefix,dataType:"json",data:b,type:this.httpMethod,beforeSend:this.displayFetchingIndication,success:this.renderIndex})},d.prototype.render=function(){var a;return a={},a[this.resourceNameSingular]=this.listItemTemplate,$(this.renderTo).html(Mustache.to_html(this.listTemplate,this.data,a)),this.removeFetchingIndication()},d}(Utilities),window.Filters=function(b){function d(b,c){var d=this;c==null&&(c={}),this.handleAdvancedOptionsClick=a(this.handleAdvancedOptionsClick,this),this.setOptions(b),this.filters=c.presets?_.keys(c.presets):[],this.setOptions(c),$("input.filter_option",this.renderTo).live("change",function(){return $(d.listSelector).trigger(d.eventName)}),$(this.advancedOptionsToggleSelector).click(this.handleAdvancedOptionsClick)}return c(d,b),d.prototype.filtersTemplate="{{#filters}}\n<div class='filter'>\n <h3>\n {{name}}\n </h3>\n <ul id='{{filter_slug}}_filter_options'>\n {{#options}}\n <label>\n <li>\n <input {{#selected}}checked='checked'{{/selected}}\n class='left filter_option'\n id='filter_{{slug}}'\n name='filters[]'\n type='checkbox'\n value='{{value}}' />\n <div class='left filter_name'>{{name}}</div>\n <div class='right filter_count'>{{count}}</div>\n <div class='clear'></div>\n </li>\n </label>\n {{/options}}\n </ul>\n</div>\n{{/filters}}",d.prototype.filterValues=function(a){return _.pluck($("."+a+"_filter_input"),"value")},d.prototype.filterSelections=function(a){return _.pluck($("#"+a+"_filter_options input.filter_option:checked"),"value")},d.prototype.render=function(a){return $(this.renderTo).html(Mustache.to_html(this.filtersTemplate,a))},d.prototype.handleAdvancedOptionsClick=function(a){return a.preventDefault(),$(this.renderTo).slideToggle()},d}(Utilities),window.Pagination=function(b){function d(b,c){c==null&&(c={}),this.handlePaginationLinkClick=a(this.handlePaginationLinkClick,this),this.pagination=null,this.maxPages=30,this.setOptions(b),this.emptyListMessage="<p>No "+this.resourceName+" matched your filter criteria</p>",this.setOptions(c),$(""+this.renderTo+" a").live("click",this.handlePaginationLinkClick)}return c(d,b),d.prototype.paginationTemplate="{{#isEmpty}}\n {{{emptyListMessage}}}\n{{/isEmpty}}\n{{^isEmpty}}\n{{#previousPage}}\n <a href='{{urlPrefix}}?page={{previousPage}}' data-page='{{previousPage}}'>← Previous</a>\n{{/previousPage}}\n{{^previousPage}}\n <span>← Previous</span>\n{{/previousPage}}\n{{#pages}}\n {{#currentPage}}\n <span>{{page}}</span>\n {{/currentPage}}\n {{^currentPage}}\n <a href='{{urlPrefix}}?page={{page}}' data-page='{{page}}'>{{page}}</a>\n {{/currentPage}}\n{{/pages}}\n{{#nextPage}}\n <a href='{{urlPrefix}}?page={{nextPage}}' data-page='{{nextPage}}'>Next →</a>\n{{/nextPage}}\n{{^nextPage}}\n <span>Next →</span>\n{{/nextPage}}\n{{/isEmpty}}",d.prototype.pagesJSON=function(a,b){var c,d,e,f,g,h;return d=this.maxPages/2,c=a<d?1:a-d,f=c+d*2-1,e=f>=b?b:f,_.map(function(){h=[];for(var a=c;c<=e?a<=e:a>=e;c<=e?a++:a--)h.push(a);return h}.apply(this),function(b){return{page:b,currentPage:function(){return a===b}}})},d.prototype.paginationJSON=function(a){return{isEmpty:a.total_pages===0,emptyListMessage:this.emptyListMessage,currentPage:a.current_page,nextPage:a.next_page,previousPage:a.previous_page,urlPrefix:this.urlPrefix,pages:this.pagesJSON(a.current_page,a.total_pages)}},d.prototype.render=function(a){return this.pagination=this.paginationJSON(a.pagination),$(this.renderTo).html(Mustache.to_html(this.paginationTemplate,this.pagination))},d.prototype.handlePaginationLinkClick=function(a){return a.preventDefault(),$(this.listSelector).trigger(this.eventName,{page:$(a.target).data("page")})},d}(Utilities),window.Search=function(b){function d(b,c){var d=this;c==null&&(c={}),this.handleSearchFormSubmit=a(this.handleSearchFormSubmit,this),this.setOptions(b),this.setOptions(c),$(this.formSelector).submit(function(a){return d.handleSearchFormSubmit(a)})}return c(d,b),d.prototype.searchTerm=function(){var a;return a=$(this.searchTextInputSelector).val(),!a||a===""?null:a},d.prototype.handleSearchFormSubmit=function(a){return a.preventDefault(),$(this.listSelector).trigger(this.eventName)},d}(Utilities)})).call(this);
1
+ ((function(){var a=function(a,b){return function(){return a.apply(b,arguments)}},b=Object.prototype.hasOwnProperty,c=function(a,c){function e(){this.constructor=a}for(var d in c)b.call(c,d)&&(a[d]=c[d]);return e.prototype=c.prototype,a.prototype=new e,a.__super__=c.prototype,a};window.Utilities=function(){function b(){this.setOptions=a(this.setOptions,this)}return b.prototype.setOptions=function(a,b){var c=this;return b==null&&(b=this),_.each(a,function(a,c){return b[c]=a})},b}(),window.LiveList=function(a){function b(a){this.globalOptions.listSelector=a.list.renderTo,this.globalOptions.eventName="livelist:"+a.global.resourceName,this.globalOptions.urlPrefix="/"+a.global.resourceName,this.setOptions(a.global,this.globalOptions),this.search=new Search(this.globalOptions,a.search),this.filters=new Filters(this.globalOptions,a.filters),this.pagination=new Pagination(this.globalOptions,a.pagination),this.list=new List(this.search,this.filters,this.pagination,this.globalOptions,a.list)}return c(b,a),b.prototype.globalOptions={data:null,resourceName:"items",resourceNameSingular:"item"},b}(Utilities),window.List=function(b){function d(b,c,d,e,f){var g,h,i=this;f==null&&(f={}),this.renderIndex=a(this.renderIndex,this),this.removeFetchingIndication=a(this.removeFetchingIndication,this),this.displayFetchingIndication=a(this.displayFetchingIndication,this),this.data=e.data,this.fetchRequest=null,this.search=b,this.filters=c,this.pagination=d,this.setOptions(e),this.listTemplate="{{#"+this.resourceName+"}}{{>"+this.resourceNameSingular+"}}{{/"+this.resourceName+"}}",this.listItemTemplate="<li>{{id}}</li>",this.fetchingIndicationClass="updating",this.setOptions(f),$(this.renderTo).bind(this.eventName,function(a,b){return i.fetch({presets:null,page:b!=null?b.page:void 0})}),jQuery.cookie&&this.filters.useCookies&&(g=jQuery.cookie(this.filters.cookieName)),this.filters.useCookies&&g?h=JSON.parse(g):h=this.filters.presets,this.fetch({presets:h})}return c(d,b),d.prototype.displayFetchingIndication=function(){return $(this.renderTo).addClass(this.fetchingIndicationClass)},d.prototype.removeFetchingIndication=function(){return $(this.renderTo).removeClass(this.fetchingIndicationClass)},d.prototype.renderIndex=function(a,b,c){return this.data=a,this.render(),this.pagination.render(this.data),this.filters.filters=_.pluck(this.data.filters,"filter_slug"),this.filters.render(this.data)},d.prototype.selections=function(){var a,b=this;return a={},_.each(this.filters.filters,function(c){return a[c]=b.filters.filterSelections(c)}),a},d.prototype.fetch=function(a){var b,c;return this.fetchRequest&&this.fetchRequest.abort(),c=this.search.searchTerm(),b={filters:{}},jQuery.isEmptyObject(a.presets)?(b.filters=this.selections(),jQuery.cookie&&!jQuery.isEmptyObject(b.filters)&&jQuery.cookie(this.filters.cookieName,JSON.stringify(b.filters))):b.filters=a.presets,c&&(b.q=c),a.page&&(b.page=a.page),this.fetchRequest=$.ajax({url:this.urlPrefix,dataType:"json",data:b,type:this.httpMethod,beforeSend:this.displayFetchingIndication,success:this.renderIndex})},d.prototype.render=function(){var a;return a={},a[this.resourceNameSingular]=this.listItemTemplate,$(this.renderTo).html(Mustache.to_html(this.listTemplate,this.data,a)),this.removeFetchingIndication()},d}(Utilities),window.LiveList.version="0.0.3",window.Filters=function(b){function d(b,c){var d=this;c==null&&(c={}),this.handleAdvancedOptionsClick=a(this.handleAdvancedOptionsClick,this),this.setOptions(b),this.filters=c.presets?_.keys(c.presets):[],this.filters.cookieName||(this.filters.cookieName="livelist_filter_presets"),this.setOptions(c),$("input.filter_option",this.renderTo).live("change",function(){return $(d.listSelector).trigger(d.eventName)}),$(this.advancedOptionsToggleSelector).click(this.handleAdvancedOptionsClick)}return c(d,b),d.prototype.filtersTemplate="{{#filters}}\n<div class='filter'>\n <h3>\n {{name}}\n </h3>\n <ul id='{{filter_slug}}_filter_options'>\n {{#options}}\n <label>\n <li>\n <input {{#selected}}checked='checked'{{/selected}}\n class='left filter_option'\n id='filter_{{slug}}'\n name='filters[]'\n type='checkbox'\n value='{{value}}' />\n <div class='left filter_name'>{{name}}</div>\n <div class='right filter_count'>{{count}}</div>\n <div class='clear'></div>\n </li>\n </label>\n {{/options}}\n </ul>\n</div>\n{{/filters}}",d.prototype.filterValues=function(a){return _.pluck($("."+a+"_filter_input"),"value")},d.prototype.filterSelections=function(a){return _.pluck($("#"+a+"_filter_options input.filter_option:checked"),"value")},d.prototype.noFiltersSelected=function(a){return _.all(a.filters,function(a){return _.all(a.options,function(a){return!a.selected})})},d.prototype.render=function(a){$(this.renderTo).html(Mustache.to_html(this.filtersTemplate,a));if(this.noFiltersSelected(a)&&a[this.resourceName].length>0)return $('input[type="checkbox"]',this.renderTo).attr("checked","checked")},d.prototype.handleAdvancedOptionsClick=function(a){return a.preventDefault(),$(this.renderTo).slideToggle()},d}(Utilities),window.Pagination=function(b){function d(b,c){c==null&&(c={}),this.handlePaginationLinkClick=a(this.handlePaginationLinkClick,this),this.pagination=null,this.maxPages=30,this.setOptions(b),this.emptyListMessage="<p>No "+this.resourceName+" matched your filter criteria</p>",this.setOptions(c),$(""+this.renderTo+" a").live("click",this.handlePaginationLinkClick)}return c(d,b),d.prototype.paginationTemplate="{{#isEmpty}}\n {{{emptyListMessage}}}\n{{/isEmpty}}\n{{^isEmpty}}\n{{#previousPage}}\n <a href='{{urlPrefix}}?page={{previousPage}}' data-page='{{previousPage}}'>← Previous</a>\n{{/previousPage}}\n{{^previousPage}}\n <span>← Previous</span>\n{{/previousPage}}\n{{#pages}}\n {{#currentPage}}\n <span>{{page}}</span>\n {{/currentPage}}\n {{^currentPage}}\n <a href='{{urlPrefix}}?page={{page}}' data-page='{{page}}'>{{page}}</a>\n {{/currentPage}}\n{{/pages}}\n{{#nextPage}}\n <a href='{{urlPrefix}}?page={{nextPage}}' data-page='{{nextPage}}'>Next →</a>\n{{/nextPage}}\n{{^nextPage}}\n <span>Next →</span>\n{{/nextPage}}\n{{/isEmpty}}",d.prototype.pagesJSON=function(a,b){var c,d,e,f,g,h;return d=this.maxPages/2,c=a<d?1:a-d,f=c+d*2-1,e=f>=b?b:f,_.map(function(){h=[];for(var a=c;c<=e?a<=e:a>=e;c<=e?a++:a--)h.push(a);return h}.apply(this),function(b){return{page:b,currentPage:function(){return a===b}}})},d.prototype.paginationJSON=function(a){return{isEmpty:a.total_pages===0,emptyListMessage:this.emptyListMessage,currentPage:a.current_page,nextPage:a.next_page,previousPage:a.previous_page,urlPrefix:this.urlPrefix,pages:this.pagesJSON(a.current_page,a.total_pages)}},d.prototype.render=function(a){return this.pagination=this.paginationJSON(a.pagination),$(this.renderTo).html(Mustache.to_html(this.paginationTemplate,this.pagination))},d.prototype.handlePaginationLinkClick=function(a){return a.preventDefault(),$(this.listSelector).trigger(this.eventName,{page:$(a.target).data("page")})},d}(Utilities),window.Search=function(b){function d(b,c){var d=this;c==null&&(c={}),this.handleSearchFormSubmit=a(this.handleSearchFormSubmit,this),this.setOptions(b),this.setOptions(c),$(this.formSelector).submit(function(a){return d.handleSearchFormSubmit(a)})}return c(d,b),d.prototype.searchTerm=function(){var a;return a=$(this.searchTextInputSelector).val(),!a||a===""?null:a},d.prototype.handleSearchFormSubmit=function(a){return a.preventDefault(),$(this.listSelector).trigger(this.eventName)},d}(Utilities)})).call(this);
@@ -27,8 +27,22 @@ module Livelist
27
27
  }
28
28
  end
29
29
 
30
+ define_method "#{filter_slug}_filter_option_key_name" do
31
+ new.respond_to?(filter_slug.to_sym) ? filter_slug.to_sym : :id
32
+ end
33
+
34
+ define_method "#{filter_slug}_filter_option_objects" do
35
+ select("distinct #{filter_slug}").all
36
+ end
37
+
30
38
  define_method "#{filter_slug}_filter_values" do
31
- select("distinct #{filter_slug}").map(&filter_slug.to_sym)
39
+ key = send("#{filter_slug}_filter_option_key_name")
40
+ option_objects = send("#{filter_slug}_filter_option_objects")
41
+ if option_objects.any?{|object| object.kind_of?(Hash) && object.has_key?(key)}
42
+ option_objects.map{|object| object[key]}
43
+ elsif option_objects.any?{|object| object.respond_to?(key)}
44
+ option_objects.map(&key)
45
+ end
32
46
  end
33
47
 
34
48
  define_method "#{filter_slug}_filter_counts" do
@@ -36,36 +50,58 @@ module Livelist
36
50
  end
37
51
 
38
52
  define_method "#{filter_slug}_filter_option_slug" do |option|
39
- option.to_s
53
+ if [String, Integer].any?{|klass| option.kind_of?(klass)}
54
+ option.to_s
55
+ else
56
+ option.send(:id).to_s
57
+ end
40
58
  end
41
59
 
42
60
  define_method "#{filter_slug}_filter_option_name" do |option|
43
- option.to_s.capitalize
61
+ option_objects = send("#{filter_slug}_filter_option_objects")
62
+ if option_objects.any?{|object| object.kind_of?(Hash) && object.has_key?(:name)}
63
+ option_object = option_objects.detect{|object| object[:state] == option.to_s}
64
+ option_object[:name]
65
+ elsif option_objects.any?{|object| object.respond_to?(:name)}
66
+ option_object = option_objects.detect{|object| object.send(:id).to_s == option.to_s}
67
+ option_object.send(:name)
68
+ else
69
+ option.to_s
70
+ end
44
71
  end
45
72
 
46
73
  define_method "#{filter_slug}_filter_option_value" do |option|
47
- option.to_s
74
+ if [String, Integer].any?{|klass| option.kind_of?(klass)}
75
+ option.to_s
76
+ else
77
+ option.send(:id).to_s
78
+ end
48
79
  end
49
80
 
50
81
  define_method "#{filter_slug}_filter_option_count" do |option|
51
82
  unless class_variables.include?("@@#{filter_slug}_filter_counts")
52
83
  class_variable_set(:"@@#{filter_slug}_filter_counts", send("#{filter_slug}_filter_counts"))
53
84
  end
54
- class_variable_get(:"@@#{filter_slug}_filter_counts")[option]
85
+ class_variable_get(:"@@#{filter_slug}_filter_counts")[option.to_s] || 0
55
86
  end
56
87
 
57
88
  define_method "#{filter_slug}_filter_option" do |option, selected|
89
+ option_slug = send("#{filter_slug}_filter_option_slug", option)
90
+ option_name = send("#{filter_slug}_filter_option_name", option)
91
+ option_value = send("#{filter_slug}_filter_option_value", option)
92
+ option_count = send("#{filter_slug}_filter_option_count", option)
93
+
58
94
  {
59
- :slug => send("#{filter_slug}_filter_option_slug", option),
60
- :name => send("#{filter_slug}_filter_option_name", option),
61
- :value => send("#{filter_slug}_filter_option_value", option),
62
- :count => send("#{filter_slug}_filter_option_count", option),
95
+ :slug => option_slug,
96
+ :name => option_name,
97
+ :value => option_value,
98
+ :count => option_count,
63
99
  :selected => selected
64
100
  }
65
101
  end
66
102
 
67
103
  define_method "#{filter_slug}_filter_option_selected?" do |filter_params, option|
68
- filter_params.nil? ? true : filter_params.include?(option)
104
+ filter_params.nil? ? false : filter_params.include?(option.to_s)
69
105
  end
70
106
 
71
107
  define_method "#{filter_slug}_filters" do |filter_params|
@@ -12,9 +12,8 @@ module Livelist
12
12
 
13
13
  if ::Rails.version < "3.1.0"
14
14
  config.before_configuration do
15
- if ::Rails.root.join("public/javascripts/livelist.min.js").exist? ||
16
- %W(production staging).include?(::Rails.env)
17
- livelist_filename = 'livelist-min'
15
+ if %W(production staging).include?(::Rails.env)
16
+ livelist_filename = 'livelist.min'
18
17
  else
19
18
  livelist_filename = 'livelist'
20
19
  end
@@ -1,7 +1,7 @@
1
1
  module Livelist
2
2
  module Rails
3
- VERSION = '0.0.4'
4
- LIVELIST_VERSION = '0.0.1'
3
+ VERSION = '0.0.5'
4
+ LIVELIST_VERSION = '0.0.3'
5
5
  MUSTACHE_VERSION = 'db5f5ece0b6c87bbb2d0584010b97f8723dde69d'
6
6
  UNDERSCORE_VERSION = '1.2.3'
7
7
  end
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  # specify any dependencies here; for example:
22
- # s.add_development_dependency "rspec"
23
- # s.add_runtime_dependency "rest-client"
22
+ s.add_development_dependency "rspec"
23
+ s.add_development_dependency "activerecord"
24
+ #s.add_runtime_dependency "rest-client"
24
25
  end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper.rb'
2
+ require File.expand_path('./lib/livelist/rails/active_record.rb')
3
+
4
+ describe Livelist::Rails::ActiveRecord do
5
+ class User
6
+ extend Livelist::Rails::ActiveRecord
7
+ filters :status, :state
8
+ end
9
+
10
+ subject { User }
11
+
12
+ context :filter_name do
13
+ it { subject.should respond_to(:state_filter_name) }
14
+ it { subject.should respond_to(:status_filter_name) }
15
+
16
+ it { subject.state_filter_name.should == 'State' }
17
+ end
18
+
19
+ context :filter_slug do
20
+ it { subject.should respond_to(:state_filter_slug) }
21
+ it { subject.should respond_to(:status_filter_slug) }
22
+
23
+ it { subject.state_filter_slug.should == 'state' }
24
+ end
25
+
26
+ context :filter do
27
+ let(:options) do
28
+ [{
29
+ :slug => 'virginia',
30
+ :name => 'Virginia',
31
+ :value => 'virginia',
32
+ :count => 1,
33
+ :selected => true
34
+ }]
35
+ end
36
+
37
+ it { subject.should respond_to(:state_filter) }
38
+ it { subject.should respond_to(:status_filter) }
39
+
40
+ it 'should be a hash with the proper keys/values' do
41
+ subject.should_receive(:state_filter_slug).and_return('state')
42
+ subject.should_receive(:state_filter_name).and_return('State')
43
+ subject.state_filter(options).should == {
44
+ :filter_slug => 'state',
45
+ :name => 'State',
46
+ :options => options
47
+ }
48
+ end
49
+ end
50
+
51
+ context :filter_values do
52
+ let(:values) do
53
+ [
54
+ double('Object', :state => 'Virginia'),
55
+ double('Object', :state => 'South Carolina')
56
+ ]
57
+ end
58
+
59
+ it { subject.should respond_to(:state_filter_values) }
60
+ it { subject.should respond_to(:status_filter_values) }
61
+
62
+ it 'should return a mapped list of values' do
63
+ subject.should_receive(:select).and_return(values)
64
+ subject.state_filter_values.should == ['Virginia', 'South Carolina']
65
+ end
66
+ end
67
+
68
+ context :filter_counts do
69
+ it { subject.should respond_to(:state_filter_counts) }
70
+ it { subject.should respond_to(:status_filter_counts) }
71
+
72
+ it 'should be tested' do
73
+ pending
74
+ end
75
+ end
76
+
77
+ context :filter_option_slug do
78
+ let(:option) { 'virginia' }
79
+
80
+ it { subject.should respond_to(:state_filter_option_slug) }
81
+ it { subject.should respond_to(:status_filter_option_slug) }
82
+
83
+ it { subject.state_filter_option_slug(option).should == 'virginia' }
84
+ end
85
+
86
+ context :filter_option_name do
87
+ let(:option) { 'virginia' }
88
+
89
+ it { subject.should respond_to(:state_filter_option_name) }
90
+ it { subject.should respond_to(:status_filter_option_name) }
91
+
92
+ it { subject.state_filter_option_name(option).should == 'Virginia' }
93
+ end
94
+
95
+ context :filter_option_value do
96
+ let(:option) { 'virginia' }
97
+
98
+ it { subject.should respond_to(:state_filter_option_count) }
99
+ it { subject.should respond_to(:status_filter_option_count) }
100
+
101
+ it { subject.state_filter_option_value(option).should == 'virginia' }
102
+ end
103
+
104
+ context :filter_option_count do
105
+ let(:option) { 'Virginia' }
106
+ let(:state_filter_counts) { { 'Virginia' => 1, 'South Carolina' => 2 } }
107
+
108
+ it { subject.should respond_to(:state_filter_option_count) }
109
+ it { subject.should respond_to(:status_filter_option_count) }
110
+
111
+ it 'option argument should be converted to a string' do
112
+ state_filter_counts['1'] = 3
113
+ subject.should_receive(:state_filter_counts).and_return(state_filter_counts)
114
+ subject.state_filter_option_count(1).should == 3
115
+ end
116
+
117
+ it 'should be the proper count for the option' do
118
+ subject.should_receive(:state_filter_counts).and_return(state_filter_counts)
119
+ subject.state_filter_option_count(option).should == 1
120
+ end
121
+
122
+ it 'should be 0 if the value for the option is nil' do
123
+ subject.should_receive(:state_filter_counts).and_return(state_filter_counts)
124
+ subject.state_filter_option_count('West Virginia').should == 0
125
+ end
126
+
127
+ it 'should cache the counts when the method is first called' do
128
+ pending
129
+ #subject.should_receive(:state_filter_counts).exactly(1).times.and_return(state_filter_counts)
130
+ #subject.state_filter_option_count(option)
131
+ #subject.state_filter_option_count('South Carolina')
132
+ end
133
+ end
134
+
135
+ context :filter_option do
136
+ let(:option) { 'virginia' }
137
+ let(:selected) { true }
138
+
139
+ it { subject.should respond_to(:state_filter_option) }
140
+ it { subject.should respond_to(:status_filter_option) }
141
+
142
+ it 'should be a properly formatted hash' do
143
+ subject.should_receive(:state_filter_option_slug).and_return('virginia')
144
+ subject.should_receive(:state_filter_option_name).and_return('Virginia')
145
+ subject.should_receive(:state_filter_option_value).and_return('virginia')
146
+ subject.should_receive(:state_filter_option_count).and_return(1)
147
+ subject.state_filter_option(option, selected).should == {
148
+ :slug => 'virginia',
149
+ :name => 'Virginia',
150
+ :value => 'virginia',
151
+ :count => 1,
152
+ :selected => true
153
+ }
154
+ end
155
+ end
156
+
157
+ context :filter_option_selected? do
158
+ let(:option) { 'Virginia' }
159
+ let(:filter_params) { ['Virginia', 'South Carolina'] }
160
+
161
+ it { subject.should respond_to(:state_filter_option_selected?) }
162
+ it { subject.should respond_to(:status_filter_option_selected?) }
163
+
164
+ it 'should be true if the option is included in the filter params' do
165
+ subject.state_filter_option_selected?(filter_params, option).should be_true
166
+ end
167
+
168
+ it 'should be true if filter params is nil' do
169
+ subject.state_filter_option_selected?(nil, option).should be_true
170
+ end
171
+
172
+ it 'should be false if the option is not included in the filter params' do
173
+ subject.state_filter_option_selected?(['West Virginia'], option).should be_false
174
+ end
175
+ end
176
+
177
+ context :filters do
178
+ it { subject.should respond_to(:state_filters) }
179
+ it { subject.should respond_to(:status_filters) }
180
+
181
+ it 'should be tested' do
182
+ pending
183
+ end
184
+ end
185
+
186
+ context :relation do
187
+ it { subject.should respond_to(:state_relation) }
188
+ it { subject.should respond_to(:status_relation) }
189
+
190
+ it 'should be tested' do
191
+ pending
192
+ end
193
+ end
194
+
195
+ context :filters_as_json do
196
+ it { subject.should respond_to(:filters_as_json) }
197
+
198
+ it 'should be tested' do
199
+ pending
200
+ end
201
+ end
202
+
203
+ context :filter do
204
+ it { subject.should respond_to(:filter) }
205
+
206
+ it 'should be tested' do
207
+ pending
208
+ end
209
+ end
210
+
211
+ end
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+
3
+ RSpec.configure do |config|
4
+ config.color_enabled = true
5
+ config.formatter = 'documentation'
6
+ end
@@ -0,0 +1,11 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: livelist-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,30 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-20 00:00:00.000000000Z
13
- dependencies: []
12
+ date: 2012-01-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &22782620 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *22782620
25
+ - !ruby/object:Gem::Dependency
26
+ name: activerecord
27
+ requirement: &22782200 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *22782200
14
36
  description: ! 'livelist-rails is a Rails 3.1 Engine/Extensiont incorporating the
15
37
  following javascript libraries: Mustache.js, underscore.js, jQuery and livelist.js,
16
38
  and providing ActiveRecord filtering extenstions.'
@@ -21,6 +43,7 @@ extensions: []
21
43
  extra_rdoc_files: []
22
44
  files:
23
45
  - .gitignore
46
+ - .rspec
24
47
  - Gemfile
25
48
  - README.md
26
49
  - Rakefile
@@ -37,6 +60,9 @@ files:
37
60
  - lib/livelist/rails/railtie.rb
38
61
  - lib/livelist/rails/version.rb
39
62
  - livelist-rails.gemspec
63
+ - spec/livelist/rails/active_record_spec.rb
64
+ - spec/livelist/spec_helper.rb
65
+ - spec/spec_helper.rb
40
66
  homepage: ''
41
67
  licenses: []
42
68
  post_install_message:
@@ -57,8 +83,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
83
  version: '0'
58
84
  requirements: []
59
85
  rubyforge_project: livelist-rails
60
- rubygems_version: 1.8.10
86
+ rubygems_version: 1.8.15
61
87
  signing_key:
62
88
  specification_version: 3
63
89
  summary: A Rails Engine/Extension Incorporating Livelist.js
64
- test_files: []
90
+ test_files:
91
+ - spec/livelist/rails/active_record_spec.rb
92
+ - spec/livelist/spec_helper.rb
93
+ - spec/spec_helper.rb