faceted_search 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -6
- data/app/assets/javascripts/faceted_search.js +7 -0
- data/app/assets/javascripts/faceted_search/Tree.js +122 -0
- data/app/assets/stylesheets/faceted_search.sass +1 -0
- data/app/assets/stylesheets/faceted_search/nestable.sass +60 -0
- data/app/models/faceted_search/facets/filter.rb +4 -4
- data/app/views/faceted_search/facets/_filter.html.erb +39 -13
- data/lib/faceted_search/version.rb +1 -1
- metadata +34 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa512c027399ad6d60bff3e93d1be82120cd70f128d4633e63d3b1fec600a230
|
4
|
+
data.tar.gz: 0aa2a2ffdf1c954d7d823af87a0ecf0532a27f5f4a3e0900448b195e5da6af43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46030dbd5f4a2ae3d85db05f19221f44cf1088cf67af67db3bc5db6b33d6cd898083c7b62ff20798bad14802dfd922d01a0976a23f0ced5289d10d8a3e8a1699
|
7
|
+
data.tar.gz: 673e5b3fefe27832dee0660014120dce7a76754dda694ef05323894d55536610adb905d6d17f9f03e3a8376bbd86ae5e6bc5e86ddfcdd8a405bccacf514444ca
|
data/README.md
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# FacetedSearch
|
2
|
-
|
2
|
+
All you need to create a faceted search, as simple as possible
|
3
3
|
|
4
|
-
|
5
|
-
How to use my plugin.
|
4
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/70579009d11cfa0d7cac/maintainability)](https://codeclimate.com/github/lespoupeesrusses/faceted_search/maintainability)
|
6
5
|
|
7
6
|
## Installation
|
8
7
|
Add this line to your application's Gemfile:
|
@@ -23,6 +22,18 @@ $ gem install faceted_search
|
|
23
22
|
|
24
23
|
## Getting started
|
25
24
|
|
25
|
+
Add to your `app/assets/stylesheets/application.sass`
|
26
|
+
```
|
27
|
+
@import 'font-awesome-sprockets'
|
28
|
+
@import 'font-awesome'
|
29
|
+
@import 'faceted_search'
|
30
|
+
```
|
31
|
+
|
32
|
+
And to your `app/assets/javascripts/application.js`
|
33
|
+
```
|
34
|
+
//= require faceted_search
|
35
|
+
```
|
36
|
+
|
26
37
|
Create a model defining your facets:
|
27
38
|
|
28
39
|
class Item::Facets < FacetedSearch::Facets
|
@@ -30,9 +41,16 @@ Create a model defining your facets:
|
|
30
41
|
super
|
31
42
|
@model = Item.all
|
32
43
|
search :title
|
33
|
-
filter :products,
|
34
|
-
|
35
|
-
|
44
|
+
filter :products, {
|
45
|
+
find_by: :title,
|
46
|
+
habtm: true
|
47
|
+
}
|
48
|
+
filter :kinds, {
|
49
|
+
habtm: true
|
50
|
+
}
|
51
|
+
filter :categories, {
|
52
|
+
habtm: true
|
53
|
+
}
|
36
54
|
end
|
37
55
|
end
|
38
56
|
|
@@ -0,0 +1,122 @@
|
|
1
|
+
/*global window, document, $ */
|
2
|
+
|
3
|
+
window.facetedSearch = window.facetedSearch || {};
|
4
|
+
|
5
|
+
window.facetedSearch.Tree = function Tree(wrapper) {
|
6
|
+
"use strict";
|
7
|
+
this.wrapper = wrapper;
|
8
|
+
this.data = [];
|
9
|
+
};
|
10
|
+
|
11
|
+
window.facetedSearch.Tree.prototype.unflatten = function (list) {
|
12
|
+
"use strict";
|
13
|
+
var map = {},
|
14
|
+
node,
|
15
|
+
roots = [],
|
16
|
+
i;
|
17
|
+
|
18
|
+
for (i = 0; i < list.length; i += 1) {
|
19
|
+
map[list[i].id] = i;
|
20
|
+
list[i].children = [];
|
21
|
+
}
|
22
|
+
|
23
|
+
for (i = 0; i < list.length; i += 1) {
|
24
|
+
node = list[i];
|
25
|
+
if (node.parentId !== 0) {
|
26
|
+
list[map[node.parentId]].children.push(node);
|
27
|
+
} else {
|
28
|
+
roots.push(node);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
return roots;
|
33
|
+
};
|
34
|
+
|
35
|
+
window.facetedSearch.Tree.prototype.generateItem = function (item) {
|
36
|
+
"use strict";
|
37
|
+
|
38
|
+
var liNode = document.createElement('li');
|
39
|
+
|
40
|
+
liNode.className = item.selected ? "dd-item dd-item--selected"
|
41
|
+
: "dd-item";
|
42
|
+
|
43
|
+
var aNode = document.createElement('a');
|
44
|
+
aNode.setAttribute("href", item.url);
|
45
|
+
aNode.textContent = item.title;
|
46
|
+
|
47
|
+
liNode.appendChild(aNode);
|
48
|
+
|
49
|
+
if (item.children.length > 0) {
|
50
|
+
var olNode = this.generateList(item.children);
|
51
|
+
liNode.appendChild(olNode);
|
52
|
+
}
|
53
|
+
|
54
|
+
return liNode;
|
55
|
+
};
|
56
|
+
|
57
|
+
window.facetedSearch.Tree.prototype.generateList = function (array) {
|
58
|
+
"use strict";
|
59
|
+
|
60
|
+
var olNode = document.createElement('ol'),
|
61
|
+
liNode,
|
62
|
+
i;
|
63
|
+
|
64
|
+
olNode.className = "faceted__facet__filter--tree__level dd-list";
|
65
|
+
|
66
|
+
for (i = 0; i < array.length; i += 1) {
|
67
|
+
liNode = this.generateItem(array[i]);
|
68
|
+
olNode.appendChild(liNode);
|
69
|
+
}
|
70
|
+
|
71
|
+
return olNode;
|
72
|
+
};
|
73
|
+
|
74
|
+
window.facetedSearch.Tree.prototype.initDOM = function () {
|
75
|
+
"use strict";
|
76
|
+
|
77
|
+
var listElements = Array.prototype.slice.call(this.wrapper.querySelectorAll('li'));
|
78
|
+
var listData = listElements.map(function (elt) {
|
79
|
+
return {
|
80
|
+
id: parseInt(elt.getAttribute('data-id'), 10),
|
81
|
+
parentId: parseInt(elt.getAttribute('data-parent'), 10),
|
82
|
+
selected: elt.getAttribute('data-selected') === "true",
|
83
|
+
resultsCount: parseInt(elt.getAttribute('data-count'), 10),
|
84
|
+
url: elt.getAttribute('data-url'),
|
85
|
+
title: elt.textContent.trim()
|
86
|
+
};
|
87
|
+
});
|
88
|
+
|
89
|
+
this.data = this.unflatten(listData);
|
90
|
+
var treeNode = this.generateList(this.data);
|
91
|
+
|
92
|
+
var rootElt = document.createElement('div');
|
93
|
+
rootElt.className = 'dd';
|
94
|
+
rootElt.appendChild(treeNode);
|
95
|
+
|
96
|
+
while (this.wrapper.firstChild) {
|
97
|
+
this.wrapper.removeChild(this.wrapper.firstChild);
|
98
|
+
}
|
99
|
+
this.wrapper.appendChild(rootElt);
|
100
|
+
};
|
101
|
+
|
102
|
+
window.facetedSearch.Tree.prototype.initNestable = function () {
|
103
|
+
"use strict";
|
104
|
+
|
105
|
+
$('.dd', this.wrapper).nestable({
|
106
|
+
expandBtnHTML: '<button class="dd-expand-btn" data-action="expand" type="button"><i class="fas fa-folder"></i></button>',
|
107
|
+
collapseBtnHTML: '<button class="dd-collapse-btn" data-action="collapse" type="button"><i class="fas fa-folder-open"></i></button>'
|
108
|
+
}).data("nestable").collapseAll();
|
109
|
+
};
|
110
|
+
|
111
|
+
window.addEventListener('DOMContentLoaded', function () {
|
112
|
+
"use strict";
|
113
|
+
var facetedTreeElts = document.querySelectorAll('.faceted__facet__filter--tree'),
|
114
|
+
facetedTree,
|
115
|
+
i;
|
116
|
+
|
117
|
+
for (i = 0; i < facetedTreeElts.length; i += 1) {
|
118
|
+
facetedTree = new window.facetedSearch.Tree(facetedTreeElts[i]);
|
119
|
+
facetedTree.initDOM();
|
120
|
+
facetedTree.initNestable();
|
121
|
+
}
|
122
|
+
});
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "faceted_search/*"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
.dd, .dd-list
|
2
|
+
position: relative
|
3
|
+
display: block
|
4
|
+
margin: 0
|
5
|
+
padding: 0
|
6
|
+
list-style: none
|
7
|
+
font-size: 13px
|
8
|
+
line-height: 20px
|
9
|
+
|
10
|
+
.dd-list .dd-list
|
11
|
+
padding-left: 26px
|
12
|
+
|
13
|
+
.dd-collapsed .dd-list
|
14
|
+
display: none
|
15
|
+
|
16
|
+
.dd-item
|
17
|
+
display: block
|
18
|
+
position: relative
|
19
|
+
margin: 3px 0 0
|
20
|
+
padding: 0
|
21
|
+
min-height: 20px
|
22
|
+
font-size: 13px
|
23
|
+
line-height: 20px
|
24
|
+
|
25
|
+
a
|
26
|
+
color: #8c8c8c
|
27
|
+
&:hover
|
28
|
+
color: #000
|
29
|
+
|
30
|
+
&--selected > a
|
31
|
+
color: #000
|
32
|
+
|
33
|
+
& > button
|
34
|
+
display: block
|
35
|
+
position: relative
|
36
|
+
cursor: pointer
|
37
|
+
float: left
|
38
|
+
width: 26px
|
39
|
+
height: 20px
|
40
|
+
margin: 0
|
41
|
+
padding: 0
|
42
|
+
text-indent: 100%
|
43
|
+
white-space: nowrap
|
44
|
+
overflow: hidden
|
45
|
+
border: 0
|
46
|
+
background: transparent
|
47
|
+
font-size: 16px
|
48
|
+
line-height: 1
|
49
|
+
text-align: center
|
50
|
+
font-weight: bold
|
51
|
+
.fas
|
52
|
+
position: absolute
|
53
|
+
top: 2px
|
54
|
+
left: -14px
|
55
|
+
&.dd-collapse-btn .fas
|
56
|
+
left: -16px
|
57
|
+
|
58
|
+
#nestable-menu
|
59
|
+
padding: 0
|
60
|
+
margin: 10px 0 20px 0
|
@@ -50,6 +50,10 @@ module FacetedSearch
|
|
50
50
|
path(custom_params.join(','))
|
51
51
|
end
|
52
52
|
|
53
|
+
def source
|
54
|
+
@options[:source] || name.to_s.singularize.titleize.constantize.send(:all)
|
55
|
+
end
|
56
|
+
|
53
57
|
protected
|
54
58
|
|
55
59
|
def params_array
|
@@ -64,10 +68,6 @@ module FacetedSearch
|
|
64
68
|
: scope.where(name => value)
|
65
69
|
end
|
66
70
|
|
67
|
-
def source
|
68
|
-
@options[:source] || name.to_s.singularize.titleize.constantize
|
69
|
-
end
|
70
|
-
|
71
71
|
def habtm?
|
72
72
|
@options[:habtm]
|
73
73
|
end
|
@@ -1,13 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
<% if facet.tree? %>
|
2
|
+
<div class="faceted__facet__filter--tree">
|
3
|
+
<div class="dd">
|
4
|
+
<ol class="faceted__facet__filter--tree__level dd-list">
|
5
|
+
<% facet.source.each do |object| %>
|
6
|
+
<%
|
7
|
+
identifier = object.send facet.find_by
|
8
|
+
results_count = facet.results_with(identifier).count
|
9
|
+
facet_url = facet.facets.path_for(facet, identifier)
|
10
|
+
display_value = facet.display_method.call(object)
|
11
|
+
selected = facet.value_selected?(identifier)
|
12
|
+
parent_id = object.parent_id.nil? ? 0 : object.parent_id
|
13
|
+
%>
|
14
|
+
<li data-parent="<%= parent_id %>"
|
15
|
+
data-id="<%= object.id %>"
|
16
|
+
data-selected="<%= selected %>"
|
17
|
+
data-url="<%= facet_url %>"
|
18
|
+
data-count="<%= results_count %>">
|
19
|
+
<%= display_value %>
|
20
|
+
</li>
|
21
|
+
<% end %>
|
22
|
+
</ol>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
<% else %>
|
26
|
+
<ul class="faceted__facet__filter list-unstyled">
|
27
|
+
<% facet.values.each do |value| %>
|
28
|
+
<%
|
29
|
+
identifier = value.send facet.find_by
|
30
|
+
results_count = facet.results_with(identifier).count
|
31
|
+
display_value = facet.display_method.call(value)
|
32
|
+
next if results_count.zero?
|
33
|
+
%>
|
34
|
+
<li class="faceted__facet__filter__value<%= '--selected' if facet.value_selected?(identifier) %>">
|
35
|
+
<%= link_to "#{display_value} (#{results_count})", facet.facets.path_for(facet, identifier) %>
|
36
|
+
</li>
|
37
|
+
<% end %>
|
38
|
+
</ul>
|
39
|
+
<% end %>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: faceted_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arnaud Levy
|
@@ -26,6 +26,34 @@ dependencies:
|
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: 5.2.2
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: font-awesome-sass
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: nestable-rails
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
29
57
|
- !ruby/object:Gem::Dependency
|
30
58
|
name: pg
|
31
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +136,10 @@ files:
|
|
108
136
|
- MIT-LICENSE
|
109
137
|
- README.md
|
110
138
|
- Rakefile
|
139
|
+
- app/assets/javascripts/faceted_search.js
|
140
|
+
- app/assets/javascripts/faceted_search/Tree.js
|
141
|
+
- app/assets/stylesheets/faceted_search.sass
|
142
|
+
- app/assets/stylesheets/faceted_search/nestable.sass
|
111
143
|
- app/models/faceted_search/facets.rb
|
112
144
|
- app/models/faceted_search/facets/default.rb
|
113
145
|
- app/models/faceted_search/facets/filter.rb
|
@@ -139,8 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
171
|
- !ruby/object:Gem::Version
|
140
172
|
version: '0'
|
141
173
|
requirements: []
|
142
|
-
|
143
|
-
rubygems_version: 2.7.6
|
174
|
+
rubygems_version: 3.0.1
|
144
175
|
signing_key:
|
145
176
|
specification_version: 4
|
146
177
|
summary: Faceted search with Active Record
|