mirror of https://github.com/flutter/samples.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.2 KiB
163 lines
4.2 KiB
import 'dart:html';
|
|
|
|
import 'package:mdc_web/mdc_web.dart';
|
|
import 'package:samples_index/browser.dart';
|
|
|
|
/// The Material text input for searching
|
|
late final MDCTextField searchBar;
|
|
late final MDCChipSet chipSet;
|
|
|
|
/// The current set of query parameters that determine how the cards are
|
|
/// filtered. e.g. {'search': 'kittens', 'platform': 'ios'}
|
|
final queryParams = <String, String>{};
|
|
const searchKey = 'search';
|
|
const typeKey = 'type';
|
|
const platformKey = 'platform';
|
|
|
|
void main() {
|
|
// Initialize Material components
|
|
MDCFloatingLabel(querySelector('.mdc-floating-label')!);
|
|
searchBar = MDCTextField(querySelector('#search-bar')!);
|
|
MDCRipple(querySelector('#clear-button')!);
|
|
|
|
// Listen for hash changes
|
|
window.onHashChange.listen((_) {
|
|
queryParams.clear();
|
|
queryParams.addAll(parseHash(window.location.hash));
|
|
setSearchBarText();
|
|
setSelectedChips();
|
|
filterCards();
|
|
});
|
|
|
|
// Use a ripple effect on all cards
|
|
querySelectorAll('.mdc-card__primary-action').forEach((el) => MDCRipple(el)
|
|
// Navigate to the description page when tapped
|
|
..listen('click', (e) {
|
|
window.location.href = el.attributes['href']!;
|
|
}));
|
|
|
|
// Filter cards on each keypress
|
|
searchBar.listen('keydown', (e) async {
|
|
await Future(() {});
|
|
handleSearch();
|
|
});
|
|
|
|
// Update the URL only when the user is done typing in the search bar
|
|
searchBar.listen('change', (e) {
|
|
queryParams[searchKey] = searchBar.value!;
|
|
updateHash();
|
|
});
|
|
|
|
// Update the hash, cards, and text input when the clear button is pressed
|
|
querySelector('#clear-button')!.onClick.listen((e) {
|
|
queryParams.remove('search');
|
|
updateHash();
|
|
setSearchBarText();
|
|
filterCards();
|
|
});
|
|
|
|
// Initialize chips
|
|
chipSet = MDCChipSet(querySelector('.mdc-chip-set')!);
|
|
chipSet.listen('MDCChip:selection', (e) {
|
|
// Get the query parameters for this chip
|
|
var selectedChipIndex = chipSet.chips.indexWhere((chip) => chip.selected!);
|
|
var chipParams = paramsForChip(selectedChipIndex);
|
|
|
|
// Overwrite query parameters with new ones
|
|
queryParams.remove(typeKey);
|
|
queryParams.remove(platformKey);
|
|
queryParams.addAll(chipParams);
|
|
updateHash();
|
|
filterCards();
|
|
});
|
|
|
|
// Apply the search from the hash in the URL
|
|
queryParams.addAll(parseHash(window.location.hash));
|
|
setSearchBarText();
|
|
setSelectedChips();
|
|
|
|
// Filter cards if a filter is being applied
|
|
if (queryParams.isNotEmpty) {
|
|
filterCards();
|
|
}
|
|
}
|
|
|
|
void setSearchBarText() {
|
|
var search = queryParams[searchKey] ?? '';
|
|
searchBar.value = search;
|
|
}
|
|
|
|
void setSelectedChips() {
|
|
var type = queryParams.containsKey(typeKey) ? queryParams[typeKey] : '';
|
|
if (type!.isNotEmpty) {
|
|
if (type == 'sample') {
|
|
chipSet.chips[1].selected = true;
|
|
}
|
|
if (type == 'cookbook') {
|
|
chipSet.chips[2].selected = true;
|
|
}
|
|
}
|
|
|
|
// Apply the platform from the hash in the URL
|
|
var platform =
|
|
queryParams.containsKey(platformKey) ? queryParams[platformKey] : '';
|
|
if (platform!.isNotEmpty) {
|
|
if (platform == 'web') {
|
|
chipSet.chips[3].selected = true;
|
|
}
|
|
}
|
|
if (platform.isEmpty && type.isEmpty) {
|
|
chipSet.chips[0].selected = true;
|
|
}
|
|
}
|
|
|
|
void handleSearch() {
|
|
var search = searchBar.value;
|
|
queryParams[searchKey] = search!;
|
|
filterCards();
|
|
}
|
|
|
|
void updateHash() {
|
|
if (queryParams.isEmpty) {
|
|
_replaceHash('');
|
|
return;
|
|
}
|
|
_replaceHash(formatHash(queryParams));
|
|
}
|
|
|
|
void _replaceHash(String hash) {
|
|
var currentUri = Uri.parse(window.location.href);
|
|
window.history
|
|
.replaceState(null, '', currentUri.replace(fragment: hash).toString());
|
|
}
|
|
|
|
void filterCards() {
|
|
// The search query, e.g. 'kittens platform:web'
|
|
var searchQuery = searchQueryFromParams(queryParams);
|
|
|
|
// Filter out all elements with non-matching search-attrs
|
|
var elements = querySelectorAll('[search-attrs]');
|
|
for (var element in elements) {
|
|
var searchAttributes = element.attributes['search-attrs'];
|
|
if (matchesQuery(searchQuery, searchAttributes!)) {
|
|
element.hidden = false;
|
|
} else {
|
|
element.hidden = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
Map<String, String> paramsForChip(int index) {
|
|
switch (index) {
|
|
case 1:
|
|
return {typeKey: 'sample'};
|
|
case 2:
|
|
return {typeKey: 'cookbook'};
|
|
case 3:
|
|
return {platformKey: 'web'};
|
|
case 0:
|
|
default:
|
|
return {};
|
|
}
|
|
}
|