livelist-rails 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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