├── src
├── index.css
├── env.js
├── app.js
└── app.css
├── .gitignore
├── package.json
└── index.html
/src/index.css:
--------------------------------------------------------------------------------
1 | body,
2 | h1 {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | body {
8 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
9 | Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
10 | }
11 |
--------------------------------------------------------------------------------
/src/env.js:
--------------------------------------------------------------------------------
1 | // Parcel picks the `source` field of the monorepo packages and thus doesn't
2 | // apply the Babel config. We therefore need to manually override the constants
3 | // in the app.
4 | // See https://twitter.com/devongovett/status/1134231234605830144
5 | global.__DEV__ = process.env.NODE_ENV !== 'production';
6 | global.__TEST__ = false;
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /dist
11 | /.cache
12 |
13 | # misc
14 | .DS_Store
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | .parcel-cache
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-instantsearch-getting-started",
3 | "version": "1.0.14",
4 | "private": true,
5 | "scripts": {
6 | "start": "BABEL_ENV=parcel parcel index.html --port 3000",
7 | "build": "BABEL_ENV=parcel parcel build index.html",
8 | "lint": "eslint .",
9 | "lint:fix": "npm run lint -- --fix"
10 | },
11 | "dependencies": {
12 | "algoliasearch": "4.14.3",
13 | "instantsearch.js": "4.56.11"
14 | },
15 | "devDependencies": {
16 | "@babel/core": "7.15.5",
17 | "@parcel/core": "2.8.0",
18 | "@parcel/packager-raw-url": "2.8.0",
19 | "@parcel/transformer-webmanifest": "2.8.0",
20 | "parcel": "2.8.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 | חיפוש בפורום פייתון
21 |
22 |
23 |
24 |
32 |
33 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | import algoliasearch from 'algoliasearch/lite';
2 | import instantsearch from 'instantsearch.js';
3 | import {
4 | configure,
5 | hits,
6 | pagination,
7 | panel,
8 | refinementList,
9 | searchBox,
10 | } from 'instantsearch.js/es/widgets';
11 |
12 | const searchClient = algoliasearch(
13 | '950FKJKDEB',
14 | 'a751cfb6edbb86ff4f5f3416b51253c0',
15 | );
16 |
17 | const search = instantsearch({
18 | indexName: 'prod_freepythoncourse',
19 | searchClient,
20 | });
21 |
22 | async function displayFirstAvailableImage(imgElement, imageUrl) {
23 | const imageUrls = [
24 | imageUrl.replace('{size}', '40').replace(".jpg", ".png"),
25 | imageUrl.replace('{size}', '40').replace(".png", ".jpg"),
26 | imageUrl.replace('{size}', '25').replace(".jpg", ".png"),
27 | imageUrl.replace('{size}', '25').replace(".png", ".jpg"),
28 | ];
29 |
30 | for (let i = 0; i < imageUrls.length; i++) {
31 | try {
32 | const response = await fetch(imageUrls[i], { method: 'HEAD' });
33 |
34 | if (response.ok) {
35 | imgElement.src = imageUrls[i];
36 | return;
37 | }
38 | } catch (error) {}
39 | }
40 |
41 | imgElement.remove();
42 | }
43 |
44 | const observer = new MutationObserver((mutationsList) => {
45 | for(const mutation of mutationsList) {
46 | if(mutation.addedNodes.length) {
47 | mutation.addedNodes.forEach((node) => {
48 | if(node.querySelectorAll) {
49 | const imgElements = node.querySelectorAll('.search-hit-avatar');
50 | imgElements.forEach(imgElement => {
51 | const imageUrl = imgElement.getAttribute('data-img');
52 | displayFirstAvailableImage(imgElement, imageUrl);
53 | });
54 | }
55 | });
56 | }
57 | }
58 | });
59 |
60 | observer.observe(document.body, { childList: true, subtree: true });
61 |
62 | search.addWidgets([
63 | searchBox({
64 | container: '#searchbox',
65 | }),
66 | hits({
67 | container: '#hits',
68 | templates: {
69 | item: (hit, { html, components }) => html`
70 |
71 |
85 |
86 | ${components.Snippet({ hit, attribute: 'cooked' })}
87 |
88 |
101 |
102 | `,
103 | },
104 | }),
105 | configure({
106 | hitsPerPage: 8,
107 | }),
108 | panel({
109 | templates: { header: "תגיות" },
110 | })(refinementList)({
111 | container: '#tags-list',
112 | attribute: 'tags',
113 | }),
114 | panel({
115 | templates: { header: "קטגוריות" },
116 | })(refinementList)({
117 | container: '#category_name-list',
118 | attribute: 'category_name',
119 | }),
120 | pagination({
121 | container: '#pagination',
122 | }),
123 | ]);
124 |
125 | search.start();
126 |
--------------------------------------------------------------------------------
/src/app.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
7 | background-color: #f8f9fa;
8 | color: #343a40;
9 | margin: 0;
10 | padding: 0;
11 | }
12 |
13 | .header {
14 | display: flex;
15 | justify-content: space-between;
16 | align-items: center;
17 | padding: 0.5rem 2rem;
18 | background-color: rgb(233, 236, 239);
19 | min-height: 40px;
20 | margin-bottom: 1rem;
21 | color: rgb(33, 37, 41);
22 | direction: rtl;
23 | }
24 |
25 | .header a {
26 | color: rgb(33, 37, 41);
27 | text-decoration: none;
28 | font-size: 1rem;
29 | margin: 0 1rem;
30 | transition: color 0.3s;
31 | }
32 |
33 | .header a:hover {
34 | color: rgb(52, 58, 64);
35 | }
36 |
37 | .header-title {
38 | font-weight: 700;
39 | font-size: 1.2rem;
40 | }
41 |
42 | .header-subtitle {
43 | font-size: 0.9rem;
44 | }
45 |
46 | @media (max-width: 600px) {
47 | .header {
48 | flex-direction: column;
49 | align-items: flex-start;
50 | padding: 0.5rem 1rem;
51 | }
52 |
53 | .header a, .header-title, .header-subtitle {
54 | margin-bottom: 0.5rem;
55 | }
56 | }
57 |
58 | .container {
59 | margin: auto;
60 | padding: 1rem;
61 | width: 100%;
62 | clear: both;
63 | }
64 |
65 | #hits {
66 | margin: 0 auto;
67 | padding: 0 1rem;
68 | width: 100%;
69 | box-sizing: border-box;
70 | }
71 |
72 | .search-panel {
73 | display: flex;
74 | flex-direction: column;
75 | gap: 1rem;
76 | }
77 |
78 | .search-panel__filters {
79 | flex: 1;
80 | }
81 |
82 | .search-panel__results {
83 | flex: 3;
84 | }
85 |
86 | .ais-Highlight-highlighted {
87 | color: inherit;
88 | font-size: inherit;
89 | }
90 |
91 | #searchbox {
92 | margin-bottom: 2rem;
93 | padding: 0.5rem;
94 | border-radius: 0.5rem;
95 | border: 1px solid #ccc;
96 | width: 100%;
97 | box-sizing: border-box;
98 | }
99 |
100 | #pagination {
101 | margin: 2rem auto;
102 | text-align: center;
103 | }
104 |
105 | @media(min-width: 600px) {
106 | .search-panel {
107 | flex-direction: row;
108 | }
109 | }
110 |
111 | .search-hit {
112 | background-color: #ffffff;
113 | border-radius: 0.75rem;
114 | padding: 1rem;
115 | margin-bottom: 1rem;
116 | width: 100%;
117 | box-sizing: border-box;
118 | box-shadow: 0 0.125rem 0.3125rem rgba(0, 0, 0, 0.1);
119 | transition: transform 0.2s;
120 | }
121 |
122 | .search-hit:hover {
123 | transform: translateY(-0.3125rem);
124 | }
125 |
126 | .search-hit-header {
127 | display: flex;
128 | flex-direction: column;
129 | align-items: flex-start;
130 | margin-bottom: 1rem;
131 | }
132 |
133 | .search-hit-header img {
134 | margin-right: auto;
135 | margin-left: auto;
136 | max-width: 100%;
137 | height: auto;
138 | }
139 |
140 | .search-hit-avatar {
141 | border-radius: 50%;
142 | width: 40px;
143 | height: 40px;
144 | margin-bottom: 1rem;
145 | object-fit: cover;
146 | }
147 |
148 | .search-hit-info {
149 | flex-grow: 1;
150 | margin-inline-start: 0.5rem;
151 | }
152 |
153 | .search-hit-title {
154 | text-align: start;
155 | direction: rtl;
156 | margin: 0;
157 | font-size: 1.5rem;
158 | line-height: 1.4;
159 | color: #343a40;
160 | }
161 |
162 | .search-hit-link {
163 | text-decoration: none;
164 | color: #007bff;
165 | }
166 |
167 | .search-hit-meta {
168 | margin: 0.3125rem 0 0 0;
169 | color: #6c757d;
170 | font-size: 0.9rem;
171 | text-align: right;
172 | direction: rtl;
173 | }
174 |
175 | .search-hit-content {
176 | margin-bottom: 1rem;
177 | }
178 |
179 | .search-hit-text {
180 | margin: 0;
181 | color: #343a40;
182 | line-height: 1.6;
183 | text-align: right;
184 | direction: rtl;
185 | }
186 |
187 | .search-hit-footer {
188 | display: flex;
189 | direction: rtl;
190 | flex-direction: column;
191 | align-items: flex-start;
192 | border-top: 1px solid #e9ecef;
193 | padding-top: 0.5rem;
194 | }
195 |
196 | .search-hit-category {
197 | display: flex;
198 | flex-grow: 1;
199 | direction: rtl;
200 | text-align: right;
201 | margin-bottom: 0.5rem;
202 | color: #6c757d;
203 | width: 10rem;
204 | }
205 |
206 | .search-hit-tags {
207 | direction: rtl;
208 | text-align: right;
209 | flex-grow: 2;
210 | color: #6c757d;
211 | margin-bottom: 0.5rem;
212 | }
213 |
214 | .search-hit-tags a {
215 | text-decoration: none;
216 | color: #007bff;
217 | }
218 |
219 | .search-hit-tags span {
220 | background-color: #e9ecef;
221 | padding: 0.125rem 0.5rem;
222 | border-radius: 0.9375rem;
223 | margin: 0 0.25rem 0.25rem 0;
224 | display: inline-block;
225 | }
226 |
227 | .search-hit-read-more {
228 | text-align: left;
229 | margin-inline-end: 0.5rem;
230 | }
231 |
232 | .search-hit-link {
233 | text-decoration: none;
234 | color: #007bff;
235 | }
236 |
237 | #pagination {
238 | margin: 2rem auto;
239 | display: flex;
240 | justify-content: space-around;
241 | flex-wrap: wrap;
242 | }
243 |
244 | .ais-Pagination-link {
245 | font-size: 0.75rem;
246 | padding: 0 0.5rem;
247 | flex: 1;
248 | text-align: center;
249 | margin: 0.5rem 0;
250 | }
251 |
252 | @media(min-width: 600px) {
253 | .ais-Pagination-link {
254 | font-size: 0.875rem;
255 | padding: 0 0.75rem;
256 | }
257 | }
258 |
259 | @media(min-width: 900px) {
260 | .ais-Pagination-link {
261 | font-size: 1rem;
262 | padding: 0 1rem;
263 | }
264 | }
265 |
266 | @media(min-width: 37.5rem) {
267 | .search-hit-header, .search-hit-footer {
268 | direction: rtl;
269 | text-align: right;
270 | flex-direction: row;
271 | align-items: center;
272 | }
273 |
274 | .search-hit-avatar {
275 | margin-bottom: 0;
276 | margin-right: 1rem;
277 | }
278 |
279 | .search-hit-category {
280 | margin-right: 0.5rem;
281 | margin-bottom: 0;
282 | }
283 |
284 | .search-hit-tags {
285 | margin-bottom: 0;
286 | }
287 | }
288 |
289 | .ais-SearchBox-form::before, .ais-SearchBox-form::before {
290 | background: initial;
291 | top: initial;
292 | width: initial;
293 | height: initial;
294 | margin-top: initial;
295 | position: initial;
296 | content: initial;
297 | left: initial;
298 | }
299 |
300 | .ais-SearchBox-form::after {
301 | background: transparent url(data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%235a5e9a%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2211%22%20cy%3D%2211%22%20r%3D%228%22%3E%3C%2Fcircle%3E%3Cline%20x1%3D%2221%22%20y1%3D%2221%22%20x2%3D%2216.65%22%20y2%3D%2216.65%22%3E%3C%2Fline%3E%3C%2Fsvg%3E) repeat scroll 0 0;
302 | content: "";
303 | height: 1rem;
304 | right: 1rem;
305 | margin-top: -0.5rem;
306 | position: absolute;
307 | top: 50%;
308 | width: 1rem;
309 | }
310 |
311 | .ais-SearchBox-form {
312 | direction: rtl;
313 | }
314 |
315 | .ais-SearchBox-form .ais-SearchBox-input {
316 | text-align: right;
317 | padding-right: 2.5rem !important;
318 | padding-left: 0 !important;
319 | }
320 |
321 | .ais-SearchBox-submit, .ais-SearchBox-reset {
322 | order: -1;
323 | left: 1rem !important;
324 | }
325 |
326 | .ais-SearchBox-reset {
327 | margin-right: auto;
328 | }
329 |
330 | .ais-RefinementList-list {
331 | direction: rtl;
332 | text-align: right;
333 | }
334 |
335 | .ais-GeoSearch-input, .ais-RefinementList-checkbox {
336 | margin: 0;
337 | margin-left: 0.5rem !important;
338 | margin-right: 0 !important;
339 | }
340 |
341 | .ais-RefinementList-count {
342 | margin-right: 0.5rem !important;
343 | margin-left: 0 !important;
344 | }
345 |
346 | .ais-Panel-header {
347 | direction: rtl;
348 | text-align: right;
349 | }
350 |
--------------------------------------------------------------------------------