فیلتر کردن یک ویژگی رایج در صفحات وب مختلف است. این به کاربران اجازه می دهد تا داده ها (مانند دسته ها، برچسب ها، سایر ویژگی ها) را با استفاده از پارامترهای ارائه شده محدود کنند. بیایید خودمان را بسازیم!
یکی از مثالهای رایج فیلتر کردن روی صفحه، یک وبسایت تجارت الکترونیک است که به کاربران اجازه میدهد محصولات را بر اساس اندازه، رنگ، نام تجاری و غیره فیلتر کنند.
در این آموزش، Tuts+ را بازسازی خواهیم کرد صفحه نویسنده و پیاده سازی یک جزء فیلتر به ما امکان می دهد مقالات را بر اساس دسته آنها فیلتر کنیم.
1. چیدمان و استایل
برای این نسخه نمایشی، صفحه نویسنده را شبیه سازی می کنیم تا نشانه گذاری و استایل مستقیماً از سایت زنده گرفته شود. اجزای اصلی که ما روی آنها تمرکز خواهیم کرد فیلترها و پست های نمایش داده شده هستند، بنابراین ما یک <div class="filter-container">
و <div class="posts-container">
و اینها را در جاوا اسکریپت هدف قرار دهید.
ما به این کانتینرها و محتوای آنها در CSS استایل می دهیم:
1 |
.posts-container { |
2 |
display: flex; |
3 |
flex-wrap: wrap; |
4 |
}
|
5 |
|
6 |
.post { |
7 |
position: relative; |
8 |
width: 300px; |
9 |
margin-right: 30px; |
10 |
margin-bottom: 40px; |
11 |
border: 1px solid #e1e8ed; |
12 |
border-radius: 4px; |
13 |
margin-top: 13px; |
14 |
min-height: 300px; |
15 |
height: auto; |
16 |
}
|
17 |
|
18 |
.filter-container { |
19 |
display: flex; |
20 |
flex-wrap: wrap; |
21 |
justify-content: flex-start; |
22 |
gap: 10px; |
23 |
padding: 32px 0; |
24 |
border-top: 1px solid #e4e4e4; |
25 |
border-bottom: 1px solid #e4e4e4; |
26 |
margin-bottom: 32px; |
27 |
}
|
28 |
|
29 |
.filter-button { |
30 |
transition: background-color 200ms, color 200ms; |
31 |
background-color: transparent; |
32 |
font: inherit; |
33 |
cursor: pointer; |
34 |
display: inline-block; |
35 |
padding: 0 8px; |
36 |
color: #717171; |
37 |
border: 1px solid #9b9b9b; |
38 |
border-radius: 25px; |
39 |
font-size: 14px; |
40 |
white-space: nowrap; |
41 |
}
|
42 |
|
43 |
.filter-button:hover { |
44 |
background-color: #f3f3f3; |
45 |
color: #3a3a3a; |
46 |
}
|
47 |
|
48 |
.filter-button.is-active { |
49 |
background-color: #0085b6; |
50 |
border-color: #0085b6; |
51 |
color: #fff; |
52 |
}
|
2. دریافت داده های صفحه با استفاده از Fetch API
در این نسخه ی نمایشی، ما از واکشی API برای بازیابی داده های ساختگی که از صفحه نویسندگان Tuts+ خراشیده شده و در a ذخیره شده اند اصل Github.
داده های ساختگی ما دارای فرمت هستند:
1 |
[
|
2 |
{
|
3 |
"https://webdesign.tutsplus.com/tutorials/title"https://webdesign.tutsplus.com/tutorials/: ""https://webdesign.tutsplus.com/tutorials/, |
4 |
"https://webdesign.tutsplus.com/tutorials/link"https://webdesign.tutsplus.com/tutorials/: ""https://webdesign.tutsplus.com/tutorials/, |
5 |
"https://webdesign.tutsplus.com/tutorials/image"https://webdesign.tutsplus.com/tutorials/: ""https://webdesign.tutsplus.com/tutorials/, |
6 |
"https://webdesign.tutsplus.com/tutorials/categories"https://webdesign.tutsplus.com/tutorials/: [ ] |
7 |
},
|
8 |
...
|
9 |
]
|
10 |
|
این اسکریپت برای واکشی داده ها از اسکریپت است:
1 |
fetch("https://webdesign.tutsplus.com/tutorials/https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials" |
2 |
).then(async (response) => { |
3 |
// handle response data
|
4 |
});
|
هنگامی که دادههای واکشی شده خود را دریافت کردیم، میتوانیم دادهها را دستکاری کرده و در صفحه اضافه کنیم.
3. افزودن داده ها به صفحه وب
برای هر شی در پاسخ واکشی شده، یک post div ایجاد می کنیم که داده ها را در صفحه نمایش می دهد. ابتدا بیایید متغیرهای جهانی خود را تعریف کنیم:
1 |
let postsData = ""https://webdesign.tutsplus.com/tutorials/; |
2 |
const postsContainer = document.querySelector("https://webdesign.tutsplus.com/tutorials/.posts-container"https://webdesign.tutsplus.com/tutorials/); |
سپس یک تابع ایجاد می کنیم createPost()
که با اضافه کردن یک div جدید به عنصر posts-container کار می کند. در این تابع یک عنصر div جدید با نام کلاس ایجاد می کنیم post
و innerHTML آن را به عنوان داده ای که می خواهیم نمایش دهیم تنظیم کنیم.
1 |
const createPost = (postData) => { |
2 |
const { title, link, image, categories } = postData; |
3 |
const post = document.createElement("https://webdesign.tutsplus.com/tutorials/div"https://webdesign.tutsplus.com/tutorials/); |
4 |
post.className = "https://webdesign.tutsplus.com/tutorials/post"https://webdesign.tutsplus.com/tutorials/; |
5 |
post.innerHTML = ` |
6 |
<a class="post-preview" href="https://webdesign.tutsplus.com/tutorials/${link}" target="_blank"> |
7 |
<img class="post-image" src="https://webdesign.tutsplus.com/tutorials/${image}"> |
8 |
</a>
|
9 |
<div class="post-content">
|
10 |
<p class="post-title">${title}</p> |
11 |
<div class="post-tags">
|
12 |
${categories |
13 |
.map((category) => { |
14 |
return "https://webdesign.tutsplus.com/tutorials/<span class="post-tag">' + category + "https://webdesign.tutsplus.com/tutorials/</span>"https://webdesign.tutsplus.com/tutorials/; |
15 |
})
|
16 |
.join(""https://webdesign.tutsplus.com/tutorials/)} |
17 |
</div>
|
18 |
</div>
|
19 |
`; |
20 |
|
21 |
postsContainer.append(post); |
22 |
};
|
در داخل پست innerHTML ما از عبارت استفاده می کنیم join("")
روش بر روی ما categories.map()
برای حذف نماد ‘،’ که در هر آرایه گنجانده شده است.
اکنون می توانیم تابع پاسخ خود را برای فراخوانی به روز کنیم createPost()
هنگامی که داده ها واکشی شدند عملکرد:
1 |
fetch("https://webdesign.tutsplus.com/tutorials/https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials" |
2 |
).then(async (response) => { |
3 |
postsData = await response.json(); |
4 |
postsData.map((post) => createPost(post)); |
5 |
});
|
4. پارامترهای فیلتر را از Response دریافت کنید
از آنجایی که ما از جاوا اسکریپت استفاده می کنیم، می توانیم از طریق پاسخ خود نقشه برداری کنیم تا یک لیست پویا از پارامترهای فیلتر ایجاد کنیم. بیایید متغیرهای سراسری را برای داده های فیلتر خود لحاظ کنیم:
1 |
let filterData = ""https://webdesign.tutsplus.com/tutorials/; |
2 |
const filterContainer = document.querySelector("https://webdesign.tutsplus.com/tutorials/.filter-container"https://webdesign.tutsplus.com/tutorials/); |
اکنون میخواهیم اسکریپتی بنویسیم که آرایههای دستهبندی را در هر شیء پاسخ مرتب کند و یک لیست منحصربهفرد برگرداند. میتوانیم شی پاسخ خود را بهروزرسانی کنیم تا بتوانیم فهرستی منحصر به فرد از پارامترهای فیلتر را دریافت کنیم
1 |
fetch("https://webdesign.tutsplus.com/tutorials/https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials" |
2 |
).then(async (response) => { |
3 |
postsData = await response.json(); |
4 |
postsData.map((post) => createPost(post)); |
5 |
فیلتر داده ها = [ |
6 |
...new Set( |
7 |
postsData
|
8 |
.map((post) => post.categories) |
9 |
.reduce((acc, curVal) => acc.concat(curVal), []) |
10 |
)
|
11 |
];
|
12 |
});
|
شکستن کد فیلتر داده ما:
- ما استفاده می کنیم
[... new Set]
برای ایجاد یک آرایه از مقادیر منحصر به فرد. تنظیم یک شی از مقادیر منحصر به فرد و نحو گسترش را برمی گرداند […] شی را به آرایه تبدیل می کند. - ما از طریق postsData نگاشت می کنیم تا آرایه دسته بندی هر شیء پست را در داخل پاسخ داده بدست آوریم.
- ما استفاده می کنیم
.reduce()
روشی برای ترکیب آرایه های دسته بندی برای هر شیء پست در یک آرایه.
هنگامی که مجموعه مقادیر فیلتر منحصربهفرد خود را از دستههای پست دریافت کردیم، میتوانیم یک تابع برای اضافه کردن هر فیلتر به صفحه ایجاد کنیم. ما یک عنصر دکمه جدید ایجاد می کنیم و innerText و className را تنظیم می کنیم. ما همچنین یک ویژگی “وضعیت داده” را برای تغییر وضعیت دکمه هنگام کلیک کردن تنظیم می کنیم.
هر دکمه فیلتر دارای یک شنونده رویداد کلیکی است که روی تابع handleButtonClick تنظیم شده است، که مسئولیت مدیریت منطق فیلتر را بر عهده خواهد داشت.
1 |
const createFilter = (filter) => { |
2 |
const filterButton = document.createElement("https://webdesign.tutsplus.com/tutorials/button"https://webdesign.tutsplus.com/tutorials/); |
3 |
filterButton.className = "https://webdesign.tutsplus.com/tutorials/filter-button"https://webdesign.tutsplus.com/tutorials/; |
4 |
filterButton.innerText = filter; |
5 |
filterButton.setAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/, "https://webdesign.tutsplus.com/tutorials/inactive"https://webdesign.tutsplus.com/tutorials/); |
6 |
filterButton.addEventListener("https://webdesign.tutsplus.com/tutorials/click"https://webdesign.tutsplus.com/tutorials/, (e) => |
7 |
handleButtonClick(e, filter) |
8 |
);
|
9 |
|
10 |
filterContainer.append(filterButton); |
11 |
};
|
و تابع پاسخ ما را برای فراخوانی به روز کنید createFilter()
تابع:
1 |
fetch("https://webdesign.tutsplus.com/tutorials/https://gist.githubusercontent.com/jemimaabu/b89339c1b7e5f81f8737fb66a858b6fc/raw/cdded4a10dbc98858481b5aedbcce3f3026dc271/tutorials" |
2 |
).then(async (response) => { |
3 |
postsData = await response.json(); |
4 |
postsData.map((post) => createPost(post)); |
5 |
فیلتر داده ها = [ |
6 |
...new Set( |
7 |
postsData
|
8 |
.map((post) => post.categories) |
9 |
.reduce((acc, curVal) => acc.concat(curVal), []) |
10 |
)
|
11 |
];
|
12 |
filterData.map((filter) => createFilter(filter)); |
13 |
});
|
5. هنگام کلیک کردن، فیلتر کردن را مدیریت کنید
اکنون دکمههای فیلتر و دادههای اولیه را دریافت کردهایم، میتوانیم عملکردی را برای فیلتر کردن دادهها با کلیک روی یک دکمه تعریف کنیم. این را می توان با استفاده از .filter()
روش در آرایه داده پست ها
این منطقی است که ما برای فیلتر کردن داده ها استفاده خواهیم کرد:
- یک تابع ایجاد کنید
handleFilterPosts()
که یک پارامتر فیلتر را می پذیرد - استفاده کنید
.filter()
روشی برای فیلتر کردن داده های پست های ما بر اساس پارامتر فیلتر - تمام عناصر موجود در posts-container را پاک کنید و filteredData جدید را به ظرف اضافه کنید.
1 |
const handleFilterPosts = (param) => { |
2 |
let filteredPosts = [...postsData].filter(post => post.categories.includes(param)) |
3 |
|
4 |
postsContainer.innerHTML = ""https://webdesign.tutsplus.com/tutorials/; |
5 |
filteredPosts.map(post => createPost(post)) |
6 |
};
|
ما می خواهیم تشخیص دهیم که چه زمانی روی یک دکمه کلیک شده است و وضعیت دکمه را به روز کنیم. در این آموزش، دکمهها را تغییر میدهیم تا اگر یک بار کلیک کنید، روی دکمه تنظیم میشود فعال و اگر دوباره کلیک کنید، دکمه روی تنظیم می شود غیر فعال.
1 |
const handleButtonClick = (e, param) => { |
2 |
const button = e.target; |
3 |
const buttonState = button.getAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/); |
4 |
|
5 |
if (buttonState =="https://webdesign.tutsplus.com/tutorials/inactive"https://webdesign.tutsplus.com/tutorials/) { |
6 |
button.classList.add("https://webdesign.tutsplus.com/tutorials/is-active"https://webdesign.tutsplus.com/tutorials/); |
7 |
button.setAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/, "https://webdesign.tutsplus.com/tutorials/active"https://webdesign.tutsplus.com/tutorials/); |
8 |
} else { |
9 |
button.classList.remove("https://webdesign.tutsplus.com/tutorials/is-active"https://webdesign.tutsplus.com/tutorials/); |
10 |
button.setAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/, "https://webdesign.tutsplus.com/tutorials/inactive"https://webdesign.tutsplus.com/tutorials/) |
11 |
}
|
12 |
}
|
همچنین میخواهیم مطمئن شویم که هر بار فقط یک دکمه انتخاب شده است و اگر هیچ دکمهای انتخاب نشده باشد، پستها باید دادههای پیشفرض را نمایش دهند تا بتوانیم توابعی برای مدیریت آن منطق ایجاد کنیم:
1 |
const resetFilterButtons = (currentButton) => { |
2 |
const filterButtons = document.querySelectorAll("https://webdesign.tutsplus.com/tutorials/.filter-button"https://webdesign.tutsplus.com/tutorials/); |
3 |
[...filterButtons].map(button => { |
4 |
if (button != currentButton) { |
5 |
button.classList.remove("https://webdesign.tutsplus.com/tutorials/is-active"https://webdesign.tutsplus.com/tutorials/); |
6 |
button.setAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/, "https://webdesign.tutsplus.com/tutorials/inactive"https://webdesign.tutsplus.com/tutorials/) |
7 |
}
|
8 |
})
|
9 |
}
|
10 |
|
11 |
const resetPosts = () => { |
12 |
postsContainer.innerHTML = ""https://webdesign.tutsplus.com/tutorials/; |
13 |
postsData.map((post) => createPost(post)); |
14 |
}
|
در نهایت، ما می توانیم عملکرد کلیک دکمه خود را به روز کنیم:
1 |
const handleButtonClick = (e, param) => { |
2 |
const button = e.target; |
3 |
const buttonState = button.getAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/); |
4 |
resetFilterButtons(button); |
5 |
|
6 |
if (buttonState =="https://webdesign.tutsplus.com/tutorials/inactive"https://webdesign.tutsplus.com/tutorials/) { |
7 |
button.classList.add("https://webdesign.tutsplus.com/tutorials/is-active"https://webdesign.tutsplus.com/tutorials/); |
8 |
button.setAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/, "https://webdesign.tutsplus.com/tutorials/active"https://webdesign.tutsplus.com/tutorials/); |
9 |
handleFilterPosts(param) |
10 |
} else { |
11 |
button.classList.remove("https://webdesign.tutsplus.com/tutorials/is-active"https://webdesign.tutsplus.com/tutorials/); |
12 |
button.setAttribute("https://webdesign.tutsplus.com/tutorials/data-state"https://webdesign.tutsplus.com/tutorials/, "https://webdesign.tutsplus.com/tutorials/inactive"https://webdesign.tutsplus.com/tutorials/) |
13 |
resetPosts() |
14 |
}
|
15 |
}
|
نتیجه
و با آن، ما به طور کامل یک جزء فیلتر برای داده ها در یک صفحه وب با استفاده از جاوا اسکریپت وانیلی ساخته ایم!