faceted_search 2.0.0 → 2.1.0
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.
- 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
|
+
[](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
|