200 lines
4.9 KiB
Rust
200 lines
4.9 KiB
Rust
use std::str::FromStr;
|
|
|
|
use chrono::Locale;
|
|
use gloo::utils::{document, window};
|
|
use wasm_bindgen::prelude::*;
|
|
use web_sys::Element;
|
|
|
|
pub trait SelectorExt {
|
|
fn selector<T>(&self, selectors: &str) -> T
|
|
where
|
|
T: JsCast;
|
|
|
|
fn selector_all<T>(&self, selectors: &str) -> Vec<T>
|
|
where
|
|
T: JsCast;
|
|
|
|
fn selector_upwards<T>(&self, selector: &str) -> Option<T>
|
|
where
|
|
T: JsCast;
|
|
|
|
fn deep_clone(&self) -> Self;
|
|
}
|
|
|
|
impl SelectorExt for Element {
|
|
fn selector<T>(&self, selectors: &str) -> T
|
|
where
|
|
T: JsCast,
|
|
{
|
|
self.query_selector(selectors)
|
|
.unwrap()
|
|
.unwrap()
|
|
.dyn_into::<T>()
|
|
.unwrap()
|
|
}
|
|
|
|
fn selector_all<T>(&self, selectors: &str) -> Vec<T>
|
|
where
|
|
T: JsCast,
|
|
{
|
|
self.query_selector_all(selectors)
|
|
.unwrap()
|
|
.values()
|
|
.into_iter()
|
|
.map(|e| e.unwrap().dyn_into::<T>().unwrap())
|
|
.collect()
|
|
}
|
|
|
|
fn selector_upwards<T>(&self, selector: &str) -> Option<T>
|
|
where
|
|
T: JsCast,
|
|
{
|
|
let mut current = self.clone();
|
|
// while let Some(parent) = current.parent_element() {
|
|
loop {
|
|
if let Ok(true) = current.matches(selector) {
|
|
return Some(current.dyn_into::<T>().unwrap());
|
|
}
|
|
|
|
if let Some(parent) = current.parent_element() {
|
|
current = parent;
|
|
} else {
|
|
return None;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn deep_clone(&self) -> Self {
|
|
self.clone_node_with_deep(true)
|
|
.unwrap()
|
|
.dyn_into::<Element>()
|
|
.unwrap()
|
|
}
|
|
}
|
|
|
|
// Not used anymore.
|
|
// pub trait NodeHelperExt {
|
|
// fn is_parent(&self, child: &Node) -> bool;
|
|
// }
|
|
// impl NodeHelperExt for Node {
|
|
// fn is_parent(&self, child: &Node) -> bool {
|
|
// let mut node = child.clone();
|
|
// while let Some(parent) = node.parent_node() {
|
|
// if &parent == self {
|
|
// return true;
|
|
// }
|
|
// node = parent;
|
|
// }
|
|
// false
|
|
// }
|
|
// }
|
|
|
|
pub fn selector<T>(selectors: &str) -> T
|
|
where
|
|
T: JsCast,
|
|
{
|
|
document()
|
|
.query_selector(selectors)
|
|
.unwrap()
|
|
.unwrap()
|
|
.dyn_into::<T>()
|
|
.unwrap()
|
|
}
|
|
|
|
pub fn selector_all<T>(selectors: &str) -> Vec<T>
|
|
where
|
|
T: JsCast,
|
|
{
|
|
document()
|
|
.query_selector_all(selectors)
|
|
.unwrap()
|
|
.values()
|
|
.into_iter()
|
|
.map(|e| e.unwrap().dyn_into::<T>().unwrap())
|
|
.collect()
|
|
}
|
|
|
|
pub fn selector_and_clone<T>(selectors: &str) -> T
|
|
where
|
|
T: JsCast,
|
|
{
|
|
document()
|
|
.query_selector(selectors)
|
|
.unwrap()
|
|
.unwrap()
|
|
.clone_node_with_deep(true)
|
|
.unwrap()
|
|
.dyn_into::<T>()
|
|
.unwrap()
|
|
}
|
|
|
|
pub fn by_id<T>(element_id: &str) -> T
|
|
where
|
|
T: JsCast,
|
|
{
|
|
document()
|
|
.get_element_by_id(element_id)
|
|
.unwrap()
|
|
.dyn_into::<T>()
|
|
.unwrap()
|
|
}
|
|
|
|
pub fn get_current_lang() -> String {
|
|
selector::<Element>("html")
|
|
.get_attribute("lang")
|
|
.unwrap()
|
|
.split("-")
|
|
.next()
|
|
.unwrap()
|
|
.to_string()
|
|
}
|
|
|
|
pub fn get_locale() -> Locale {
|
|
let lang_and_territory = selector::<Element>("html")
|
|
.get_attribute("lang")
|
|
.unwrap()
|
|
.replace("-", "_");
|
|
Locale::from_str(&lang_and_territory).unwrap_or_default()
|
|
}
|
|
|
|
/// Extracts and remove some URL parameters from the current URL.
|
|
pub fn extract_get_parameters(names: &[&str]) -> Vec<(String, String)> {
|
|
let mut param_values = vec![];
|
|
let location = window().location();
|
|
|
|
if let Ok(search) = location.search() {
|
|
if !search.is_empty() && search.starts_with('?') {
|
|
let mut search_chars = search.chars();
|
|
search_chars.next(); // To remove the first character which is '?'.
|
|
let mut new_search = String::with_capacity(search.len());
|
|
for kv in search_chars.as_str().split('&') {
|
|
match kv.split('=').collect::<Vec<&str>>()[..] {
|
|
[key, value] if names.contains(&key) => {
|
|
param_values.push((key.to_string(), value.to_string()));
|
|
}
|
|
_ => {
|
|
if !new_search.is_empty() {
|
|
new_search.push('&');
|
|
}
|
|
new_search.push_str(kv);
|
|
}
|
|
}
|
|
}
|
|
|
|
if !param_values.is_empty() {
|
|
let mut new_url = location.pathname().unwrap();
|
|
if !new_search.is_empty() {
|
|
new_url.push('?');
|
|
new_url.push_str(&new_search);
|
|
}
|
|
window()
|
|
.history()
|
|
.unwrap()
|
|
.push_state_with_url(&JsValue::null(), "", Some(&new_url))
|
|
.unwrap();
|
|
}
|
|
}
|
|
}
|
|
|
|
param_values
|
|
}
|