' );
_e( '
' );
_e( '
' );
_e( '
' );
_e( '
保存配置生效后, 用于快捷发布, 自动发布, 和其他地方发布
).'images/fat-rat-256x256.png'); ?>)
announcement('notice-debug')); ?>
| 地址: | 此处可以填写你要爬取的地址. 列表页/详情页 地址 均可 |
|---|---|
| 编码处理: | 自动识别(推荐) 删HEAD(非UTF-8编码推荐) 强制转换(终方) |
| 采集方式: | 静态渲染 动态渲染 |
| 范围: |
填写Html标签的 class 或者 id (Jquery语法) 参考 |
| 采集规则: |
规则名 - JQuery选择器
- 属性 - 标签过滤: 空格分割 参考 | 语法 ---* 内容过滤Jquery常用语法: :eq(等于) :gt(大于) :lt(小于) :first(第一个) :last(最后一个) :even(偶数) :odd(奇数) 更多 |
|
首先, 打开开发者工具, Chrome浏览器控制台打开方法: 右键->检查->console, 其他浏览器大同小异. 点击debugging后请看控制台Console里面的数据, 文字教程, 视频教程中 均有介绍如何使用, 照葫芦画瓢. 视频教程, 文字教程已经写的很详细了, 如果你没有耐心花30分钟熟悉胖鼠、可在插件管理->选择胖鼠->卸载 = - =! / 或者来骚扰下作者 代写 采集中心所有采集均支持debugging模式哦、最后如果胖鼠采集帮助到你, 请支持一下开源作品 插件五星好评支持 |
|
| getAppreciatesHtml(7)); ?> | |
' ) !== false){ return; } $cats = collect(get_the_category($postID)); if ($cats->isEmpty()) { return ; } $cat_ids = $cats->pluck('term_id'); $args = array('orderby' => 'rand','showposts' => 1,'cat' => $cat_ids->implode(','), 'date_query' => array( 'column' => 'post_date', 'after' => date('Y-m-d H:i:s', strtotime(current_time('mysql'))-(3600*24*57)), 'before' => current_time('mysql') )); $query_posts = new WP_Query(); $posts_data = $query_posts->query($args); if (empty($posts_data)) { return ; } /* if (isset($posts_data[0]) && $previous_post = $posts_data[0]){ $link = get_permalink($previous_post->ID); $pre_string = sprintf('%s', $link, $previous_post->post_title, wp_trim_words($previous_post->post_content, 130)); $content = $pre_string.$content; } */ if (isset($posts_data[0]) && $next_post = $posts_data[0]){ $link = get_permalink($next_post->ID); $next_string = sprintf('%s
相关推荐: %s', $link, $next_post->post_title, wp_trim_words($next_post->post_content, 130)); $content = $content.$next_string; } wp_update_post(array('ID' => $postID, 'post_content' => $content)); } } if (!function_exists("frc_image")) { /** * @param $file * @return string */ function frc_image($file){ $model = new FRC_Kit(); esc_html_e($model->kit_image_path($file)); } } function frc_auto_task($postID){ $model = new FRC_Kit(); $model->kit_auto_tags($postID); $model->kit_dynamic_fields($postID); } add_action('publish_post', 'frc_auto_task'); $result = get_option(FRC_Validation::FRC_VALIDATION_INNER_CHAIN); if ($result && @json_decode($result)->switch === 'open'){ function frc_inner_chain( $post_content ) { $config = json_decode(get_option(FRC_Validation::FRC_VALIDATION_INNER_CHAIN)); $limit = isset($config->limit) ? $config->limit : 1; collect(get_tags( array('hide_empty' => false) ))->map(function ($tag) use (&$post_content, $limit){ if ( stristr($post_content,$tag->name) !== false) { $link = get_tag_link($tag->term_id); $keyword = stripslashes($tag->name); $url = sprintf('%s', $link, $keyword, $keyword); $regEx = '\'(?!((<.*?)|(%s
]*?)>)|([^>]*?))\'s'; $post_content = preg_replace($regEx, $url, $post_content, $limit); } }); return $post_content; } add_filter('the_content','frc_inner_chain'); } function frc_kit(){ $frc_validation_tags = get_option(FRC_Validation::FRC_VALIDATION_AUTO_TAGS); $frc_validation_chain = get_option(FRC_Validation::FRC_VALIDATION_INNER_CHAIN); $frc_validation_dynamic = get_option(FRC_Validation::FRC_VALIDATION_DYNAMIC_FIELDS); $frc_validation_automatic_save_pic = get_option(FRC_Validation::FRC_VALIDATION_AUTOMATIC_SAVE_PIC); $frc_validation_release_control = get_option(FRC_Validation::FRC_VALIDATION_RELEASE_CONTROL); $frc_validation_insert_keyword = get_option(FRC_Validation::FRC_VALIDATION_INSERT_KEYWORD); $frc_validation_wechat_history = get_option(FRC_Validation::FRC_VALIDATION_WECHAT_HISTORY); $frc_validation_sponsorship = get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP); $frc_wp_schedules = wp_get_schedules(); array_multisort(array_column($frc_wp_schedules, 'interval'), SORT_ASC, $frc_wp_schedules); ?> option($option_id); // 全站采集转义数据处理 if ($option['collect_type'] == 'all'){ $option['collect_list_range'] = str_replace("\\\\", "\\", htmlspecialchars_decode($option['collect_list_range'])); } // 转义数据处理 $option['collect_keywords_replace_rule'] = str_replace(" ", "\n", $option['collect_keywords_replace_rule']); $custom_content = json_decode(!empty($option['collect_custom_content'])?$option['collect_custom_content']:'{"head":"","foot":""}', true); $custom_content['head'] = str_replace('\\"', '"', htmlspecialchars_decode($custom_content['head'])); $custom_content['foot'] = str_replace('\\"', '"', htmlspecialchars_decode($custom_content['foot'])); // TODO: optimized $list_rules = translationRules($option['collect_list_rules']); $rule_link = [ 'a' => 'link', 'b' => $list_rules['link']['selector']??'', 'c' => $list_rules['link']['attribute']??'', 'd' => $list_rules['link']['filter']??'', ]; foreach (translationRules($option['collect_content_rules']) as $key => $val){ $value = [ 'a' => $key, 'b' => $val['selector'], 'c' => $val['attribute'], 'd' => $val['filter'], ]; if ($key == 'title'){ $rule_title = $value; } elseif ($key == 'content'){ $rule_content = $value; } elseif ($key == 'paging'){ $rule_paging = $value; } } } $frc_validation_sponsorship = get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP); $frc_validation_all_collect = get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT); ?>
![]()
欢迎来到胖鼠工具箱
胖鼠采集定时任务列表
$cron){ if (!is_array($cron)){ continue; } foreach ($cron as $key => $value){ if ($key == 'frc_cron_release_hook'){ $frc_cron_release_boolean = true; _e(sprintf('', date('Y-m-d h:i:s', strtotime("+8 hours", $time)))); } if ($key == 'frc_cron_spider_hook'){ $frc_cron_spider_boolean = true; _e(sprintf('', date('Y-m-d h:i:s', strtotime("+8 hours", $time)))); } } } if (!$frc_cron_release_boolean){ _e(''); } if (!$frc_cron_spider_boolean){ _e(''); } ?>
鼠友你好, 如果您遇到定时任务不起作用, 是因为WP-Cron无法连续运行,这是一个wp问题。
有一个简单的解决方案。只需将系统的任务计划程序设置为在所需的时间间隔(或在所需的特定时间)运行。最简单的解决方案是使用工具向wp-cron.php文件发出Web请求。
在系统上安排任务之后,还有一个步骤要完成。WordPress将在每次加载页面时继续运行WP-Cron。这不再是必需的,它将导致服务器上额外的资源使用。可以在wp-config.php文件中禁用WP-Cron
1, 打开/wp-config.php文件进行编辑,并添加以下行:
define('DISABLE_WP_CRON', true);2, 添加系统定时任务 你要使用的命令是:
2选1即可
wget -qO- &> /dev/null
curl &> /dev/null.
1, 第一步可优化节省服务器资源, 避免用户每次访问都查询cron, 优化服务速度
2, 第二步是执行一个定时的请求, 每隔 5 - 15 分钟(推荐五分钟), 请求站点的/wp-cron.php文件
linux OR ubuntu window 宝塔 都可以配置, 具体操作咨询服务商或百度
设置完成之后, 自动采集, 自动发布. 时间很准
全站采集
全站采集
![]()
动态渲染
全站采集
![]()
自动采集
- > 关闭此功能
$info){ $disabled = ''; if (empty($frc_validation_sponsorship) && $info['interval']<43200){ $disabled = 'disabled'; } _e(sprintf('- %s(%s秒)
', $key, (!empty($cron_spider) && $cron_spider == $key ? esc_html('checked') : ''), $disabled, $info['display'], $info['interval'])); } ?>胖鼠工具箱首页可看到爬虫目前的简单状态哦, 后续慢慢优化哦
或者下载安装插件 Advanced Cron Manager 里面 frc_ 开头的就是咱们的定时自动任务, 其他类似插件均可
自动发布
请鼠友给胖鼠五星评分, 感谢!
- > 关闭此功能
$info){ $disabled = ''; if (empty($frc_validation_sponsorship) && $info['interval']<43200){ $disabled = 'disabled'; } _e(sprintf('- %s(%s秒)
', $key, (!empty($cron_release) && $cron_release == $key ? esc_html('checked') : ''), $disabled, $info['display'], $info['interval'])); } ?>自动标签
'); } ?>Auto Tags (文章自动打标签)
此功能不依赖胖鼠采集, 属可独立运行功能!
自动标签意指为文章自动打标签!
第一步把你的标签输入进标签库!
新发布的文章会在发布的同时, 会自动匹配标签库标签.
关键词命中就会自动打标签, 升级后英文不区分大小写.
省时省力还省心!
switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态'; $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动'; _e(sprintf('%s
', $switch_text)); _e(sprintf('', $subsequent_text)); } ?>标签内链
'); } ?>开启后会给文章中的标签增加标签列表页的链接
每个标签目前只增加一次链接
配合自动标签更完美, 省时省力还省心.
switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态'; $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动'; _e(sprintf('%s
', $switch_text)); _e(sprintf('', $subsequent_text)); } ?>动态内容
'); } ?>Dynamic Content (文章自动添加动态内容)
动态内容不依赖胖鼠采集, 属可独立运行功能!
动态内容是为文章自动添加一段动态内容!
指在文章正文开头、结尾各插入一段其他文章内容 (新版本去掉开头的内容)
插入的内容来自: 同分类下,最近七天的随机文章,如果没有找到七天内文章, 就不添加
文章正文前后插入内容后, 有利于收录, 并且不影响用户阅读.
动态内容胖鼠推荐使用!!! 省时省力还省心!
您已激活成功
switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态'; $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动'; _e(sprintf('%s
', $switch_text)); _e(sprintf('', $subsequent_text)); } ?>数据发布控制
'); } ?>此功能激活后: 可操作发布页面所有选项。
您已激活成功
关键词随机插入
'); } ?> switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态'; $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动'; _e(sprintf('%s
', $switch_text)); _e(sprintf('', $subsequent_text)); } ?>从其他站点手动复制过来的文章,点击保存后,所有远程图片自动本地化
待开发
'); } ?>开启后会给文章中的标签增加标签列表页的链接
每个标签目前只增加一次链接
配合自动标签更完美, 省时省力还省心.
switch == 'open' ? '此功能目前是启动状态' : '此功能目前是关闭状态'; $subsequent_text = $conf_json->switch == 'open' ? '点击关闭' : '点击启动'; _e(sprintf('%s
', $switch_text)); _e(sprintf('', $subsequent_text)); } ?>公众号历史文章采集
'); } ?>感谢支持
鼠友限时享有胖鼠采集公众号历史文章采集功能wpdb = $wpdb; $this->table_options = $wpdb->prefix . 'frc_options'; } /** * @param int $page_number * @param int $per_page * @param string $customvar * * @return array */ public function options_paging(int $page_number = 1, int $per_page = 10, string $customvar = 'total'): array { $sql = "SELECT * FROM $this->table_options"; if (in_array($customvar, array('list', 'single', 'all'))) { $sql = $this->wpdb->prepare("$sql where `collect_type` = '%s'", $customvar); } if (!empty($_REQUEST['orderby'])) { $by = frc_sanitize_text('orderby'); $sort = !empty($_REQUEST['order']) ? frc_sanitize_text('order') : 'ASC'; $sql = $this->wpdb->prepare("$sql ORDER BY $by $sort"); } else { $sql .= ' ORDER BY id DESC'; } $sql = $this->wpdb->prepare("$sql LIMIT %d OFFSET %d", (int) $per_page, (int) (($page_number - 1) * $per_page)); return $this->wpdb->get_results($sql, 'ARRAY_A'); } /** * @return array|null|object */ public function options(){ return $this->wpdb->get_results($this->wpdb->prepare("select * from %i ",$this->table_options),ARRAY_A); } /** * @param int $option_id * @return array|null|object|void */ public function option(int $option_id): array { return $this->wpdb->get_row($this->wpdb->prepare("select * from $this->table_options where `id` = %d", $option_id),ARRAY_A); } /** * @param $id * @return false|int */ public function delete($id) { $re = $this->wpdb->delete( $this->table_options, array('id' => $id), array('%d') ); (new FRC_Data())->delete_by_option($id); return $re; } /** * @param $name * @return array|null|object|void */ public function lazy_person($name){ $option = $this->option_by_key($name, 'collect_name'); if (empty($option)){ // 默认生成基础配置 $this->insert_option($name); $option = $this->option_by_key($name, 'collect_name'); } return $option; } /** * @param $name * @param $key * @return array|null|object|void */ public function option_by_key($name, $key) { return $this->wpdb->get_row($this->wpdb->prepare("SELECT * FROM {$this->table_options} WHERE `{$key}` = '%s'", $name), ARRAY_A ); } /** * @param string $customvar * @return null|string */ public function record_count(string $customvar = 'total') { $sql = "SELECT COUNT(*) FROM $this->table_options"; if (in_array($customvar, array('list', 'single', 'all', 'keyword'))) { $sql = $this->wpdb->prepare("$sql where collect_type = %s", $customvar); } return $this->wpdb->get_var($sql); } /** * @param $name * @return array|null|object|void */ public function insert_option($name) { $date = current_time('mysql'); if ($name == '微信'){ $sql = "INSERT INTO `{$this->table_options}` SET `collect_name` = '微信', `collect_describe` = '胖鼠采集. WordPress 最好用的采集小插件. ', `collect_type` = 'single', `collect_image_attribute` = 'data-src', `collect_content_range` = '#img-content', `collect_content_rules` = 'title%#activity-name|text|null)(content%#js_content|html|null)(author%#js_author_name|text|null)(name%#js_name|text|null', `created_at` = '{$date}', `updated_at` = '{$date}'"; } elseif ($name == '简书'){ $sql = "INSERT INTO `{$this->table_options}` SET `collect_name` = '简书', `collect_describe` = '胖鼠采集. WordPress 最好用的采集小插件. ', `collect_type` = 'single', `collect_image_attribute` = 'data-original-src', `collect_content_range` = 'body', `collect_content_rules` = 'title%h1:first|text|null)(content%article|html|a', `created_at` = '{$date}', `updated_at` = '{$date}'"; } elseif ($name == '知乎'){ $sql = "INSERT INTO `{$this->table_options}` SET `collect_name` = '知乎', `collect_describe` = '胖鼠采集. WordPress 最好用的采集小插件. ', `collect_type` = 'single', `collect_image_attribute` = 'data-actualsrc', `collect_content_range` = '.App-main', `collect_content_rules` = 'title%.QuestionHeader-title|text|null)(content%.RichContent-inner|html|a -.LinkCard-content', `created_at` = '{$date}', `updated_at` = '{$date}'"; } else { return ; } return $this->wpdb->query($sql); } /** * @return array */ public function interface_save_option(){ if (!get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP)){ if (count($this->options()) > 5){ return ['code' => FRC_ApiError::FAIL, 'msg' => FRC_Validation::FRC_HINT_Z]; } } $option_id = frc_sanitize_text('option_id', null); $collect_name = frc_sanitize_text('collect_name'); $collect_describe = frc_sanitize_text('collect_describe', '胖鼠采集, Wordpress最好用的采集神器.'); $collect_type = frc_sanitize_text('collect_type', 'list'); $collect_cookie = frc_sanitize_text('collect_cookie', ''); $collect_rendering = (int) frc_sanitize_text('collect_rendering', 1); $collect_image_download = (int) frc_sanitize_text('collect_image_download', 1); $collect_image_path = (int) frc_sanitize_text('collect_image_path', 1); $collect_remove_head = (int) frc_sanitize_text('collect_remove_head', 1); $collect_list_url = frc_sanitize_text('collect_list_url'); $collect_list_url_paging = frc_sanitize_text('collect_list_url_paging'); $collect_list_range = frc_sanitize_text('collect_list_range'); $collect_list_rules = frc_sanitize_text('collect_list_rules'); $collect_content_range = frc_sanitize_text('collect_content_range'); $collect_content_rules = frc_sanitize_text('collect_content_rules'); $collect_image_attribute = frc_sanitize_text('collect_image_attribute', 'src'); $collect_custom_content_head = frc_sanitize_textarea('collect_custom_content_head'); $collect_custom_content_foot = frc_sanitize_textarea('collect_custom_content_foot'); $collect_keywords_replace_rule = frc_sanitize_text('collect_keywords_replace_rule'); $collect_keywords = frc_sanitize_textarea('collect_keywords', ''); if ($collect_name == ''){ return ['code' => FRC_ApiError::FAIL, 'msg' => '给你的配置写个名字吧, 着啥急']; } if ($collect_type == 'list'){ if ($collect_list_url == ''){ return ['code' => FRC_ApiError::FAIL, 'msg' => '请填写采集地址.']; } if (empty($collect_list_range) || empty($collect_list_rules)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '列表采集范围/采集规则为空.']; } } if (empty($collect_content_range) || empty($collect_content_rules)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '详情采集范围/采集规则为空.']; } if ($collect_keywords != ''){ $collect_keywords = str_replace('\"', '"', htmlspecialchars_decode($collect_keywords, ENT_QUOTES)); if (!json_decode($collect_keywords)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '关键词随机插入Json错误']; } } $params = [ 'collect_name' => $collect_name, 'collect_describe' => $collect_describe, 'collect_type' => $collect_type, 'collect_cookie'=>$collect_cookie, 'collect_rendering' => $collect_rendering, 'collect_image_download' => $collect_image_download, 'collect_image_path' => $collect_image_path, 'collect_remove_head' => $collect_remove_head, 'collect_list_url' => $collect_list_url, 'collect_list_url_paging' => $collect_list_url_paging, 'collect_list_range' => $collect_list_range, 'collect_list_rules' => $collect_list_rules, 'collect_content_range' => $collect_content_range, 'collect_content_rules' => $collect_content_rules, 'collect_image_attribute' => $collect_image_attribute, 'collect_custom_content' => json_encode(['head' => $collect_custom_content_head, 'foot' => $collect_custom_content_foot]), 'collect_keywords_replace_rule' => $collect_keywords_replace_rule, 'collect_keywords' => $collect_keywords, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ]; // Tips: 优化掉 if (in_array($collect_name, FRC_ApiError::BUTTON_DISABLED)){ // add author name variable if ($collect_name == '微信'){ $params['collect_content_rules'] = $params['collect_content_rules'].')(author%#js_author_name|text|null)(name%#js_name|text|null'; } elseif ($collect_name == '简书'){ $params['collect_content_rules'] = $params['collect_content_rules'].')(author%span[class=name]|text|null'; } } if ($option_id === null){ if (in_array($collect_name, FRC_ApiError::BUTTON_DISABLED)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '不可使用这个配置名称!']; } if ($this->wpdb->insert($this->table_options, $params)) { return ['code' => FRC_ApiError::SUCCESS, 'msg' => 'Creating Success.']; } else { $error = $this->wpdb->last_error; return ['code' => FRC_ApiError::FAIL, 'msg' => 'Creating error. ' . $error]; } } if (false !== $this->wpdb->update($this->table_options, $params, ['id' => $option_id], ['%s', '%s'], ['%d'])) { return ['code' => FRC_ApiError::SUCCESS, 'msg' => ' Update Success.']; } else { $error = $this->wpdb->last_error; return ['code' => FRC_ApiError::FAIL, 'msg' => 'Update error. ' . $error]; } } /** * @return array */ public function interface_save_option_release(){ $option_id = frc_sanitize_text('option_id', null); if (!$option_id){ return ['code' => FRC_ApiError::SUCCESS, 'msg' => 'option id error.']; } $msg = '保存完成.'; if (get_option(FRC_Validation::FRC_VALIDATION_RELEASE_CONTROL)){ $params = [ 'category' => frc_sanitize_array('release_category', 'integer'), 'user' => frc_sanitize_array('release_user', 'integer'), 'status' => frc_sanitize_text('release_status', 'pending'), 'type' => frc_sanitize_text('release_type', 'post'), 'thumbnail' => frc_sanitize_text('release_thumbnail', 'thumbnail1'), 'release_type' => frc_sanitize_text('release_type', 'WordPress'), 'extension_field' => frc_sanitize_text('extension_field', 'post'), ]; if (empty($params['category'])){ $params['category'] = array(1); } if (empty($params['user'])){ $params['user'] = [get_current_user_id()]; } } else { $msg = FRC_Validation::FRC_HINT_L; $params = [ 'category' => array(1), 'user' => [get_current_user_id()], 'status' => frc_sanitize_text('release_status', 'pending'), 'thumbnail' => 'thumbnail2', 'release_type' => 'WordPress', 'type' => 'post', 'extension_field' => 'post', ]; } $result = $this->wpdb->update($this->table_options, ['collect_release' => json_encode($params)], ['id' => $option_id], ['%s', '%s'], ['%d'] ); return ['code' => FRC_ApiError::SUCCESS, 'msg' => $msg, 'data' => $result]; } /** * @return array */ public function interface_import_default_configuration(){ $default_configurations = collect([ [ 'collect_name' => '胖鼠采集-御龙在天', 'collect_describe' => '列表采集规则, 页面编码GBK 小提示 如果class有两个属性,选一个唯一的即可 | ul li 中间还可以加空格哦知道什么意思吗?', 'collect_type' => 'list', 'collect_list_url' => 'https://yl.qq.com/webplat/info/news_version3/118/430/m279/list_1.shtml', 'collect_list_url_paging' => 'https://yl.qq.com/webplat/info/news_version3/118/430/m279/list_{page}.shtml', 'collect_list_range' => '.news_list ul li', 'collect_list_rules' => 'link%a:eq(1)|href|null', 'collect_content_range' => '.center_part', 'collect_content_rules' => 'title%.news_h2|text|null)(content%.news_content|html|null', 'collect_image_attribute' => 'src', 'collect_remove_head' => '2', 'collect_charset' => 'gbk', 'collect_custom_content' => '{"head":"","foot":""}', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ], [ 'collect_name' => '胖鼠采集-寻仙', 'collect_describe' => '列表采集规则, 页面编码GBK, 曾经玩过这个游戏至今念念不忘. 小提示 仔细看配置 选择元素第二个a标签用 eq 语法', 'collect_type' => 'list', 'collect_list_url' => 'https://xx.qq.com/webplat/info/news_version3/154/2233/3889/m2702/list_1.shtml', 'collect_list_url_paging' => 'https://xx.qq.com/webplat/info/news_version3/154/2233/3889/m2702/list_{page}.shtml', 'collect_list_range' => '.down-nr>ul>li', 'collect_list_rules' => 'link%a:eq(1)|href|null', 'collect_content_range' => '.sub-cont', 'collect_content_rules' => 'title%.n_title|text|null)(content%.sub-nr|html|null', 'collect_image_attribute' => 'src', 'collect_remove_head' => '3', 'collect_charset' => 'gbk', 'collect_custom_content' => '{"head":"","foot":""}', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ], [ 'collect_name' => '胖鼠采集-虎扑', 'collect_describe' => '地址: https://voice.hupu.com/sports', 'collect_type' => 'single', 'collect_content_range' => '.voice-main', 'collect_content_rules' => 'title%.artical-title>h1|text|null)(content%.artical-content|html|null', 'collect_image_attribute' => 'src', 'collect_remove_head' => '1', 'collect_charset' => 'utf-8', 'collect_custom_content' => '{"head":"","foot":""}', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ], [ 'collect_name' => '胖鼠采集-直播8', 'collect_describe' => '地址: https://news.zhibo8.cc/nba/more.htm', 'collect_type' => 'single', 'collect_content_range' => '#main', 'collect_content_rules' => 'title%h1|text|null)(content%div[class=content]|html|null', 'collect_image_attribute' => 'src', 'collect_remove_head' => '1', 'collect_charset' => 'utf-8', 'collect_custom_content' => '{"head":"","foot":""}', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ], [ 'collect_name' => '胖鼠采集-小故事', 'collect_describe' => '内容分页采集例子 http://www.xigushi.com/aqgs/3262.html', 'collect_type' => 'single', 'collect_content_range' => '.by', 'collect_content_rules' => 'title%h1|text|null)(content%dl>dd>p|html|a)(paging%.page a:contains(下一页)|href|null', 'collect_image_attribute' => 'src', 'collect_remove_head' => '2', 'collect_charset' => 'utf-8', 'collect_custom_content' => '{"head":"","foot":""}', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ], ]); $default_configurations->map(function($default_config){ if (!$this->wpdb->get_row( $this->wpdb->prepare("SELECT * FROM $this->table_options WHERE `collect_name` = %s limit 1", $default_config['collect_name']) , ARRAY_A )){ $this->wpdb->insert($this->table_options, $default_config, ['%s', '%s']); } }); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '完成, 快来走进胖鼠采集的世界吧. ']; } /** * @return array */ public function interface_del_option(){ if(!current_user_can( 'manage_options' )){ wp_send_json(['code' => 5006, 'msg' => FRC_Validation::FRC_HINT_M]); wp_die(); } $option_id = frc_sanitize_text('option_id', null); if (empty($option_id)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '配置ID错误']; } return ['code' => FRC_ApiError::SUCCESS, 'msg' => '删除成功', 'data' => $this->delete($option_id)]; } /** * @return array */ public function interface_upgrade(){ if ('upgrade complete' == get_option('frc_mysql_upgrade')){ return ['code' => FRC_ApiError::SUCCESS, 'msg' => '升级完成']; } $progress = frc_sanitize_text('progress'); if ($progress == '1'){ $former_table_options = $this->wpdb->prefix . 'fr_options'; $res = $this->wpdb->get_results("SHOW TABLES LIKE '%{$former_table_options}%'"); if (empty($res)){ update_option('frc_mysql_upgrade', '2'); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '配置表升级完成.']; } $data = $this->wpdb->get_results("select * from $former_table_options", ARRAY_A); foreach ($data as $option){ $params = [ 'id' => $option['id'], 'collect_name' => $option['collect_name'], 'collect_describe' => $option['collect_describe'], 'collect_type' => $option['collect_type'], 'collect_cookie' => $option['collect_cookie'], 'collect_rendering' => 1, 'collect_image_download' => $option['collect_image_download'], 'collect_image_path' => $option['collect_image_path'], 'collect_remove_head' => ($option['collect_remove_head'] == 0) ? 1 : 2, 'collect_list_url' => $option['collect_list_url'], 'collect_list_url_paging' => '', 'collect_list_range' => $option['collect_list_range'], 'collect_list_rules' => $option['collect_list_rules'], 'collect_content_range' => $option['collect_content_range'], 'collect_content_rules' => $option['collect_content_rules'], 'collect_image_attribute' => $option['collect_image_attribute'], 'collect_custom_content' => $option['collect_custom_content'], 'collect_keywords_replace_rule' => $option['collect_keywords_replace_rule'], 'collect_charset' => $option['collect_charset'], 'created_at' => $option['created'], 'updated_at' => $option['created'], ]; $this->wpdb->insert($this->table_options, $params); } update_option('frc_mysql_upgrade', '2'); //$this->wpdb->query( "DROP TABLE IF EXISTS $former_table_options" ); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '配置系统、升级完成.']; } if ($progress == '2'){ $former_table_post = $this->wpdb->prefix . 'fr_post'; $res = $this->wpdb->get_results("SHOW TABLES LIKE '%{$former_table_post}%'"); if (empty($res)){ update_option('frc_mysql_upgrade', 'upgrade complete'); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '升级完成.']; } try{ $last_id = get_option('frc_mysql_upgrade_progress', 0); $data = $this->wpdb->get_results($this->wpdb->prepare("select `id`, `title`, `content`, `image`, `post_type`, `link`, `post_id`, `is_post`, `created` from $former_table_post where id > %d limit 500", $last_id), ARRAY_A); if (empty($data)){ delete_option('frc_mysql_upgrade_progress'); update_option('frc_mysql_upgrade', 'upgrade complete'); //$this->wpdb->query( "DROP TABLE IF EXISTS $former_table_post" ); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '数据系统,升级完成.']; } foreach ($data as $post){ $params = [ 'id' => $post['id'], 'option_id' => $post['post_type'], 'status' => ($post['is_post'] == 0) ? 2 : 3, 'title' => $post['title'], 'cover' => $post['image'], 'content' => $post['content'], 'link' => $post['link'], 'post_id' => $post['post_id'], 'message' => 'migration data.', 'created_at' => $post['created'], 'updated_at' => $post['created'], ]; try{ $this->wpdb->replace($this->wpdb->prefix.'frc_post', $params); } catch (Exception $e){ } } $last_id = update_option('frc_mysql_upgrade_progress', end($data)['id']); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '数据系统,分段升级进行中, 分段升级市为避免大数据量鼠升级失败提供的, 目前已经升级进度'.$last_id.'条, 请继续点击红色按钮进行下一段升级']; } catch (Exception $e) { return ['code' => FRC_ApiError::SUCCESS, 'msg' => '异常,数据导入失败.']; } } return ['code' => FRC_ApiError::SUCCESS, 'msg' => '升级完成']; } /** * @return array */ public function interface_update_auto_config(){ $option = frc_sanitize_text('option'); $value = frc_sanitize_text('value'); if (empty($option)){ return ['code' => FRC_ApiError::FAIL, 'msg' => 'Operation Key Error!']; } if (!strstr($option, 'frc_')){ return ['code' => FRC_ApiError::FAIL, 'msg' => 'Off the white list.']; } $data = update_option($option, $value); wp_clear_scheduled_hook($option.'_hook'); return ['code' => FRC_ApiError::SUCCESS, 'msg' => '设置完成.', 'data' => $data]; } } class FRC_Configuration_List_Table extends WP_List_Table { /** * Retrieve snippets data from the database * * @param int $per_page * @param int $page_number * * @return mixed */ public static function get_snippets($per_page = 10, $page_number = 1, $customvar = 'total') { $model = new FRC_Options(); $result = $model->options_paging($page_number, $per_page, $customvar); return collect($result)->map(function ($data){ $data['collect_auto_collect'] = '完善中'; $data['collect_auto_release'] = '完善中'; return $data; }); } /** * Delete a snipppet record. * @param $id * @return false|int */ public function delete_snippet($id) { $model = new FRC_Options(); return $model->delete($id); } /** * Activate a snipppet record. * * @param int $id snippet ID */ public static function activate_snippet($id) { } /** * Deactivate a snipppet record. * * @param int $id snippet ID */ public static function deactivate_snippet($id) { } /** * Returns the count of records in the database. * * @return null|string */ public static function record_count($customvar = 'total') { $model = new FRC_Options(); return $model->record_count($customvar); } /** Text displayed when no snippet data is available */ public function no_items() { esc_html_e('配置空空的, 请创建采集配置开始旅程吧, 如果你快速认识胖鼠, 可以使用上面一键导入默认配置来学习.', 'Fat Rat Collect'); } /** * Render a column when no column specific method exist. * * @param array $item * @param string $column_name * * @return mixed */ public function column_default($item, $column_name) { switch ($column_name) { case 'collect_image_download' : switch ($item[$column_name]){ case '1': return esc_html('下载到本地'); break; case '2': return esc_html('不下载'); break; case '3': return esc_html('清除所有图片'); break; } break; case 'collect_image_path' : switch ($item[$column_name]){ case '1': return esc_html('绝对路径'); break; case '2': return esc_html('相对路径'); break; } case 'collect_list_url' : return sprintf("%s", $item[$column_name], $item[$column_name]); break; case 'collect_describe': return esc_html(mb_substr($item[$column_name], 0, 30) . ' ...'); break; case 'collect_type' : switch ($item[$column_name]){ case 'list': return esc_html('列表采集'); break; case 'single': return esc_html('详情采集'); break; case 'all': return esc_html('全站采集'); break; case 'keyword': return esc_html('关键字采集'); break; } break; case 'collect_name': $title = '' . $item['collect_name'] . ''; $actions = array( '修改' => sprintf("%s", admin_url('admin.php?page=frc-options-add-edit&option_id=' . $item['id']), esc_html__('修改', 'Fat Rat Collect')), '删除' => sprintf("", $item['id'], esc_html__('删除', 'Fat Rat Collect')), ); return $title . $this->row_actions( $actions ); break; case 'collect_keywords_replace_rule' : return esc_html('... 点击查看'); break; default: return esc_html($item[$column_name]); break; } } /** * Render the bulk edit checkbox * * @param array $item * * @return string */ function column_cb($item) { return sprintf( '', $item['id'] ); } /** * Method for name column * * @param array $item an array of DB data * * @return string */ function column_name($item) { } /** * Associative array of columns * * @return array */ function get_columns() { $columns = array( 'cb' => '', 'id' => esc_html__('ID', 'Fat Rat Collect'), 'collect_name' => esc_html__('配置名称', 'Fat Rat Collect'), 'collect_describe' => esc_html__('配置描述', 'Fat Rat Collect'), 'collect_type' => esc_html__('采集类型', 'Fat Rat Collect'), 'collect_list_url' => esc_html__('采集地址', 'Fat Rat Collect'), // 'collect_auto_collect' => esc_html__('自动采集', 'Fat Rat Collect'), // 'collect_auto_release' => esc_html__('自动发布', 'Fat Rat Collect'), 'collect_list_url' => esc_html__('采集地址', 'Fat Rat Collect'), 'collect_image_download' => esc_html__('下载图片', 'Fat Rat Collect'), 'collect_image_path' => esc_html__('图片使用路径', 'Fat Rat Collect'), 'collect_image_attribute' => esc_html__('目标图片源属性', 'Fat Rat Collect'), 'created_at' => esc_html__('创建时间', 'Fat Rat Collect'), ); return $columns; } /** * Columns to make sortable. * * @return array */ public function get_sortable_columns() { return array( 'id' => array('id', false), ); } /** * Returns an associative array containing the bulk action * * @return array */ public function get_bulk_actions() { return array( 'bulk-todo' => esc_html__('敬请期待', 'Fat Rat Collect'), // 'bulk-start-collect' => esc_html__('开启自动采集', 'Fat Rat Collect'), // 'bulk-stop-collect' => esc_html__('关闭自动采集', 'Fat Rat Collect'), // 'bulk-start-release' => esc_html__('开启自动采集', 'Fat Rat Collect'), // 'bulk-stop-release' => esc_html__('关闭自动采集', 'Fat Rat Collect'), ); } /** * Handles data query and filter, sorting, and pagination. */ public function prepare_items() { $columns = $this->get_columns(); $hidden = array(); $sortable = $this->get_sortable_columns(); //Retrieve $customvar for use in query to get items. $customvar = frc_sanitize_text('customvar', 'total'); $this->_column_headers = array($columns, $hidden, $sortable); /** Process bulk action */ $this->process_bulk_action(); $this->views(); $per_page = $this->get_items_per_page('snippets_per_page', 10); $current_page = $this->get_pagenum(); $total_items = self::record_count(); $this->set_pagination_args(array( 'total_items' => $total_items, 'per_page' => $per_page, )); $this->items = self::get_snippets($per_page, $current_page, $customvar); } public function get_views() { $views = array(); $current = frc_sanitize_text('customvar', 'total'); // 假设这里的 `frc_sanitize_text` 已确保安全 // 总计 $class = 'total' === $current ? ' class="current"' : ''; $total_url = esc_url(remove_query_arg('customvar')); // 转义 URL $views['total'] = sprintf( '%s (%d)', $total_url, esc_attr($class), esc_html__('全部配置', 'Fat Rat Collect'), $this->record_count() ); // 列表采集 $foo_url = esc_url(add_query_arg('customvar', 'list')); // 转义 URL $class = ('list' === $current ? ' class="current"' : ''); $views['list'] = sprintf( '%s (%d)', $foo_url, esc_attr($class), esc_html__('列表采集', 'Fat Rat Collect'), $this->record_count('list') ); // 详情采集 $bar_url = esc_url(add_query_arg('customvar', 'single')); // 转义 URL $class = ('single' === $current ? ' class="current"' : ''); $views['single'] = sprintf( '%s (%d)', $bar_url, esc_attr($class), esc_html__('详情采集', 'Fat Rat Collect'), $this->record_count('single') ); // 全站采集(可选) if (get_option(FRC_Validation::FRC_VALIDATION_ALL_COLLECT)) { $all_url = esc_url(add_query_arg('customvar', 'all')); // 转义 URL $class = ('all' === $current ? ' class="current"' : ''); $views['all'] = sprintf( '%s (%d)', $all_url, esc_attr($class), esc_html__('全站采集', 'Fat Rat Collect'), $this->record_count('all') ); } return $views; } public function process_bulk_action() { // If the delete bulk action is triggered if ( ( isset( $_POST['action'] ) && 'bulk-delete' === $_POST['action'] ) || ( isset( $_POST['action2'] ) && 'bulk-delete' === $_POST['action2'] ) ) { // $delete_ids = esc_sql( $_POST['snippets'] ); // // // loop over the array of record IDs and delete them // foreach ( $delete_ids as $id ) { // $this->delete_snippet( $id ); // } // // return; } } } function frc_options() { $snippet_obj = new FRC_Configuration_List_Table(); ?> wpdb = $wpdb; $this->table_post = $wpdb->prefix . 'frc_post'; } /** * 懒人采集 * @return array */ public function grab_custom_page(){ $urls = frc_sanitize_text('collect_urls'); $name = frc_sanitize_text('collect_name'); if (empty($urls)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '链接不能为空']; } if (empty($name) || !in_array($name, ['wx', 'js', 'zh'])){ return ['code' => FRC_ApiError::FAIL, 'msg' => '链接不能为空']; } switch ($name){ case 'wx': $name = '微信'; $urls = $this->wx_url_format($urls); break; case 'js': $name = '简书'; break; case 'zh': $name = '知乎'; break; } $options = new FRC_Options(); $option = $options->lazy_person($name); return $this->response(FRC_ApiError::SUCCESS, $this->single_spider($option, $urls), $name .'数据处理完成, F12可查看单条数据具体采集结果喔'); } private function wx_url_format($urls){ $urls = explode(' ', $urls); foreach ($urls as &$url){ $i = strpos($url, '&chksm'); if ($i === false){ continue; } $url = substr($url, 0, $i); } return join(' ', $urls); } /** * 抓取详情 * @return array */ public function grab_details_page(){ $urls = frc_sanitize_text('collect_details_urls'); $option_id = frc_sanitize_text('collect_details_relus', 0); if (empty($urls)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '链接不能为空']; } if (empty($option_id)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '请选择一个有效的详情配置']; } $options = new FRC_Options(); $option = $options->option($option_id); if (!$option) { return ['code' => FRC_ApiError::FAIL, 'msg' => '未查询到配置, 配置ID错误']; } return $this->response(FRC_ApiError::SUCCESS, $this->single_spider($option, $urls)); } /** * 列表采集 * @return array */ public function grab_list_page() { $option_id = frc_sanitize_text('option_id', 0); $options = new FRC_Options(); $option = $options->option($option_id); if (!$option) { return ['code' => FRC_ApiError::FAIL, 'msg' => '未查询到配置, 配置ID错误']; } $config = new stdClass(); $config->url = $option['collect_list_url']; $config->range = $option['collect_list_range']; $config->rules = $this->rulesFormat($option['collect_list_rules']); $config->rendering = $option['collect_rendering']; $config->remove_head = $option['collect_remove_head']; $config->image_download = $option['collect_image_download']; $config->image_path = $option['collect_image_path']; $config->src = $option['collect_image_attribute']; isset($option["collect_cookie"]) && $config->cookie = $option["collect_cookie"]; $articles = $this->_QlObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) { if ($this->checkPostLink($item['link'])){ return $this->format($item, '已滤重'); } $config->url = $item['link']; $config->range = $option['collect_content_range']; $config->rules = $this->rulesFormat($option['collect_content_rules']); $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->special($config)->query()->getDataAndRelease(); $detail = array_merge($item, empty($detail)?[]:current($detail)); $this->paging($detail, $config); return $this->insert_article($detail, $option); })->getDataAndRelease(); return $this->response(FRC_ApiError::SUCCESS, $articles, '列表采集完成'); } /** * 历史(分页)页面 */ public function grab_history_page() { $history_page_number = frc_sanitize_text('collect_history_page_number'); $option_id = frc_sanitize_text('collect_history_relus_id', null); if ($option_id === null){ return ['code' => FRC_ApiError::FAIL, 'msg' => '请选择一个配置']; } $options = new FRC_Options(); $option = $options->option($option_id); if (!$option) { return ['code' => FRC_ApiError::FAIL, 'msg' => '请选择一个有效的配置, 配置异常']; } if (empty($history_page_number)){ return ['code' => FRC_ApiError::FAIL, 'msg' => '请填写页码/翻页']; } if (empty($option['collect_list_url_paging'])){ return ['code' => FRC_ApiError::FAIL, 'msg' => '请配置分页采集地址']; } if ($option['collect_rendering'] == 1){ if (!strstr($option['collect_list_url_paging'], '{page}')){ return ['code' => FRC_ApiError::FAIL, 'msg' => 'URL不正确。未包含 {page} 关键字 or URL不能为空']; } $page_count = explode('-', $history_page_number); $page_count = count($page_count) == 2 ? range($page_count[0], $page_count[1]) : [(int)$page_count[0]]; if (!get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP) && count($page_count) > 3){ return ['code' => FRC_ApiError::FAIL, 'msg' => FRC_Validation::FRC_HINT_F]; } $articles = collect($page_count)->map(function($digital) use ($option){ $config = new stdClass(); $config->url = $option['collect_list_url_paging']; $config->range = $option['collect_list_range']; $config->rules = $this->rulesFormat($option['collect_list_rules']); $config->rendering = $option['collect_rendering']; $config->remove_head = $option['collect_remove_head']; $config->image_download = $option['collect_image_download']; $config->image_path = $option['collect_image_path']; $config->src = $option['collect_image_attribute']; $config->pn = $digital; $result['url'] = str_replace('{page}', $config->pn, $config->url); $article = $this->_QlPagingObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) { if ($this->checkPostLink($item['link'])){ return $this->format($item, '已滤重'); } $config->url = $item['link']; $config->range = $option['collect_content_range']; $config->rules = $this->rulesFormat($option['collect_content_rules']); $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->special($config)->query()->getDataAndRelease(); $detail = array_merge($item, empty($detail)?[]:current($detail)); $this->paging($detail, $config); return $this->insert_article($detail, $option); })->getDataAndRelease(); $result['data'] = $article; return $result; }); } else { $config = new stdClass(); $config->url = $option['collect_list_url']; $config->range = $option['collect_list_range']; $config->rules = $this->rulesFormat($option['collect_list_rules']); $config->rendering = $option['collect_rendering']; $config->remove_head = $option['collect_remove_head']; $config->image_download = $option['collect_image_download']; $config->image_path = $option['collect_image_path']; $config->src = $option['collect_image_attribute']; $config->pn = $history_page_number; $article = $this->_QlPagingObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) { if ($this->checkPostLink($item['link'])){ return $this->format($item, '已滤重'); } $config->url = $item['link']; $config->range = $option['collect_content_range']; $config->rules = $this->rulesFormat($option['collect_content_rules']); $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->query()->getDataAndRelease(); $detail = array_merge($item, current($detail)??''); $this->paging($detail, $config); return $this->insert_article($detail, $option); })->getDataAndRelease(); $articles['rolling'] = $history_page_number; $articles['data'] = $article; } return $this->response(FRC_ApiError::SUCCESS, $articles, '分页采集完成'); } /** * @return array */ public function grab_all_page() { $option_id = frc_sanitize_text('option_id', 0); $options = new FRC_Options(); $option = $options->option($option_id); if (!$option) { return ['code' => FRC_ApiError::FAIL, 'msg' => '未查询到配置, 配置ID错误']; } $config = new stdClass(); $config->url = $option['collect_list_url']; $config->range = $option['collect_list_range']; //$config->rules = $this->rulesFormat($option['collect_list_rules']); $config->rendering = $option['collect_rendering']; $config->remove_head = $option['collect_remove_head']; $config->image_download = $option['collect_image_download']; $config->image_path = $option['collect_image_path']; $config->src = $option['collect_image_attribute']; $config->pure = true; // TODO: 优化内存使用 $articles = $this->_QlObject($config)->absoluteUrl($config)->find('a')->attrs('href')->filter(function ($item) use ($config) { if ($item === null){ return false; } $config->range = str_replace("\\\\", "\\", htmlspecialchars_decode($config->range)); $pattern = '/'.str_replace('/', '\/', $config->range).'/'; if (preg_match($pattern, $item, $matches)){ return true; } return false; }); $articles = $articles->map(function ($link) use ($config, $option) { $item['link'] = $link; if ($this->checkPostLink($item['link'])){ return $this->format($item, '已滤重'); } $config->url = $item['link']; $config->range = $option['collect_content_range']; $config->rules = $this->rulesFormat($option['collect_content_rules']); $config->pure = false; $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->query()->getDataAndRelease(); $detail = array_merge($item, empty($detail)?[]:current($detail)); $this->paging($detail, $config); return $this->insert_article($detail, $option); }); return $this->response(FRC_ApiError::SUCCESS, $articles, '全站采集完成'); } /** * @return array */ public function grab_debug(){ $config = new stdClass(); $config->url = frc_sanitize_text('debug_url'); $config->range = frc_sanitize_text('debug_range'); $config->rules = $this->rulesFormat(frc_sanitize_text('debug_rules')); $config->rendering = frc_sanitize_text('debug_rendering', 1); $config->remove_head = frc_sanitize_text('debug_remove_head', 1); if (empty($config->url)){ return $this->response(FRC_ApiError::SUCCESS, null, '请输入参数.'); } $detail = $this->_QlObject($config)->absoluteUrl($config)->query()->getDataAndRelease(); return $this->response(FRC_ApiError::SUCCESS, $detail, '调试完成, 请在F12中查看'); } /** * 微信公众号历史文章采集 */ function grab_wechat_history() { $appName = frc_sanitize_text('collect_wechat_app_name'); $startNumber = frc_sanitize_text('collect_wechat_app_start_number'); $page = frc_sanitize_text('collect_wechat_app_number'); $cookie = frc_sanitize_text('collect_wx_app_cookie'); $token = frc_sanitize_text('collect_wx_app_token'); $auth = get_option('frc_validation_wechat_history'); if (empty($auth)) return $this->response(FRC_ApiError::FAIL, null, '激'.'活后才'.'能使'.'用哦'); $auth = json_decode($auth,true); //if (isset($auth['expireDate']) && time() > $auth['expireDate']) return $this->response(FRC_ApiError::FAIL, null, '试用结束啦,请赞赏后试用~'); if (empty($appName) || empty($startNumber) || empty($page) || empty($cookie) || empty($token)) return $this->response(FRC_ApiError::FAIL, null, '请检查提交参数,所有参数均不可为空'); if ($page > 30) return $this->response(FRC_ApiError::FAIL, null, '为保护鼠友账号安全,单次采集最大页数暂定不超过30页'); $cookie = explode("; ",$cookie); $cookieData = []; foreach ($cookie as $item) { $item = explode("=",$item); $cookieData[$item[0]] = isset($item[1]) ? $item[1] : ""; } $cookieJar = \GuzzleHttp\Cookie\CookieJar::fromArray($cookieData,"mp.weixin.qq.com"); $client = new \GuzzleHttp\Client(); //ps 优化点 这个fakeid 可以存在option里 不用每次都去查 $url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?action=search_biz&begin=0&count=5&token='.$token.'&lang=zh_CN&f=json&ajax=1&query='.urlencode($appName); $result = $client->request("get",$url,[ "cookies"=>$cookieJar ]) ->getBody() ->getContents(); if (!empty($result)) { $result = json_decode($result,true); if (!isset($result["base_resp"]["ret"]) && $result["base_resp"]["ret"] != 0) return $this->response(FRC_ApiError::FAIL, null, '请检查公众号名称是否有误,未搜索到相关公众号'); $list = $result["list"]; $fakeId = ''; foreach ($list as $item) { if ($item["nickname"] == $appName) { $fakeId = $item['fakeid']; } } if (empty($fakeId)) return $this->response(FRC_ApiError::FAIL, null, '请检查公众号名称是否有误,未搜索到相关公众号'); $listUrl = 'https://mp.weixin.qq.com/cgi-bin/appmsgpublish?sub=list&search_field=null&'; $options = new FRC_Options(); $option = $options->lazy_person("微信"); if (!$this->checkWechatHistoryTimeLimit($page)) return $this->response(FRC_ApiError::FAIL, null, '为保护鼠友公众号安全,单日采集最大页数不能超过500页'); for ($i = 0; $i < $page; $i++) { sleep(3); $begin = $startNumber == 1 ? 0 : $startNumber * 20 + $i * 20; $listUrl .= 'begin='.$begin.'&count=20&query=&fakeid='.$fakeId.'&type=101_1&free_publish_type=1&sub_action=list_ex&token='.$token.'&lang=zh_CN&f=json&ajax=1'; $result = $client->request("get",$listUrl,[ "cookies"=>$cookieJar ]) ->getBody() ->getContents(); if (!empty($result)) { $result = json_decode($result, true); if (!isset($result["base_resp"]["ret"]) && $result["base_resp"]["ret"] != 0) return $this->response(FRC_ApiError::FAIL, null, $result["base_resp"]["err_msg"]); $publishPage = json_decode($result["publish_page"],true); foreach ($publishPage["publish_list"] as $item) { //每期发布的文章 $articles = json_decode($item["publish_info"],true)['appmsgex']; foreach ($articles as $article) { //每期的每一篇文章 if ($this->checkPostLink($article['link'])) continue; $data['status'] = 1; $data['option_id'] = $option['id']; $data['cover'] = isset($article['cover']) ? $article['cover'] : ''; $data['link'] = $article['link']; $data['title'] = mb_substr($this->text_keyword_replace($article['title'], $option), 0, 120); $data['content'] = ""; $data['message'] = 'Wait.'; $data['created_at'] = current_time('mysql'); $data['updated_at'] = current_time('mysql'); $this->wpdb->insert($this->table_post, $data); } } return $this->response(FRC_ApiError::SUCCESS, null, "采集完成,请到数据桶查看"); }else{ return $this->response(FRC_ApiError::FAIL, null, '网络错误, 请重试. '); } } }else return $this->response(FRC_ApiError::FAIL, null, '网络错误, 请重试. '); } /** * @param $option * @param $urls * @return array|bool */ public function single_spider($option, $urls) { if ($option['collect_type'] != 'single'){ return ['message' => '任务类型错误', 'data' => $option]; } $config = new stdClass(); $config->url = ''; $config->range = $option['collect_content_range']; $config->rules = $this->rulesFormat($option['collect_content_rules']); $config->rendering = $option['collect_rendering']; $config->remove_head = $option['collect_remove_head']; $config->image_download = $option['collect_image_download']; $config->image_path = $option['collect_image_path']; $config->src = $option['collect_image_attribute']; isset($option["collect_cookie"]) && $config->cookie = $option["collect_cookie"]; $article = collect(explode(' ', $urls))->map(function($url) use ($config, $option) { $config->url = $url; $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->special($config)->query()->getDataAndRelease(); $detail = array_merge(['link' => $url], (array)current($detail)); $this->paging($detail, $config); $option["url"] = $url; return $this->insert_article($detail, $option); }); return ['message' => '处理完成', 'data' => $article]; } /** * @param $detail * @param $config */ private function paging(&$detail, $config) { $i = 1; $maximum = 50; $detail['paging'] = AbsoluteUrl::urlFormat($detail['paging']??'', $config->url); // url format if (!empty($detail['paging'])) { $config->url = $detail['paging']; while (true) { $pagging = $this->_QlObject($config) ->absoluteUrl($config) ->downloadImage($config) ->special($config) ->query()->getDataAndRelease(); $pagging = current($pagging); $pagging['paging'] = AbsoluteUrl::urlFormat($pagging['paging'], $config->url); $detail['content'] .= $pagging['content']; if (empty($pagging['paging']) || $pagging['paging'] == $config->url || $i > $maximum) { break; } $config->url = AbsoluteUrl::urlFormat($pagging['paging'], $config->url); // url format $detail['paging_'.$i] = $config->url; $i++; } } } /** * @param $text * @param $option * @return mixed */ private function text_keyword_replace($text, $option) { if (!$text || !$option) { return $text; } $keywords_array = explode(" ", trim($option['collect_keywords_replace_rule'])); collect($keywords_array)->map(function ($keywords) use (&$text) { if (empty($keywords)){ return ; } list($string, $replace) = explode('=', $keywords); $text = str_replace($string, $replace, $text); }); return preg_replace('##' , '' , $text); // 去掉注释 } /** * 定时爬虫 * @return array */ public function timing_spider() { $options = collect((new FRC_Options())->options()); $re = $options->reverse()->map(function ($option){ if ($option['collect_type'] == 'single'){ return $this->format($option, '详情采集不支持自动'); } $config = new stdClass(); $config->url = $option['collect_list_url']; $config->range = $option['collect_list_range']; $config->rules = $this->rulesFormat($option['collect_list_rules']); $config->rendering = $option['collect_rendering']; $config->remove_head = $option['collect_remove_head']; $config->image_download = $option['collect_image_download']; $config->image_path = $option['collect_image_path']; $config->src = $option['collect_image_attribute']; // 采集列表 $articles = $this->_QlObject($config)->absoluteUrl($config)->query(function($item) use ($option, $config) { if ($this->checkPostLink($item['link'])){ return $this->format($item, '已滤重'); } // 采集详情 $config->url = $item['link']; $config->range = $option['collect_content_range']; $config->rules = $this->rulesFormat($option['collect_content_rules']); $detail = $this->_QlObject($config)->absoluteUrl($config)->downloadImage($config)->query()->getDataAndRelease(); $detail = array_merge($item, empty($detail)?[]:current($detail)); $this->paging($detail, $config); return $this->insert_article($detail, $option); })->getDataAndRelease(); return $articles; }); return ['message' => '处理完成', 'data' => $re]; } /** * @param $option * @return QueryList */ public function _QlObject($option) { $config = new \stdClass; $config->url = $option->url; $config->range = $option->range; $config->rules = $option->rules; $config->rendering = $option->rendering; $config->remove_head = $option->remove_head; $config->pure = isset($option->pure) && $option->pure === true ? true : false; $ql = $this->_QlInstance(); if (!$config->pure) { $ql->rules($config->rules)->range($config->range); } $head = [ 'timeout' => 100 ]; if ($option->cookie) { $head['headers'] = [ 'Cookie' => $option->cookie, ]; } try{ if ($config->rendering == 1) { if ($config->remove_head == 3){ $ql->getTransCoding($config->url); } else { $ql->get( $config->url ,null, $head); } } elseif ($config->rendering == 2) { $ql->use(Chrome::class); $options = ['args' => ['--no-sandbox', '--disable-setuid-sandbox'], 'timeout' => 10000]; $ql->chrome($config->url, $options); } } catch (Exception $e){ $ql->setHtml(''); // http error } $ql->encoding('UTF-8'); if (strstr('2-3', $config->remove_head)) { $ql->removeHead(); } return $ql; } /** * @param $option * @return QueryList */ public function _QlPagingObject($option) { $config = new \stdClass; $config->url = $option->url; $config->range = $option->range; $config->rules = $option->rules; $config->rendering = $option->rendering; $config->remove_head = $option->remove_head; $config->pn = $option->pn; $ql = $this->_QlInstance()->rules($config->rules)->range($config->range); try{ if ($config->rendering == 1) { $url = str_replace('{page}', $config->pn, $config->url); if ($config->remove_head == 3){ $ql->getTransCoding($url); } else { $ql->get($url, [], ['timeout' => 10]); } } elseif ($config->rendering == 2) { $ql->use(Chrome::class); $options = ['args' => ['--no-sandbox', '--disable-setuid-sandbox'], 'timeout' => 10000]; $ql->chrome(function ($page, $browser) use ($config) { $page->goto($config->url); for ($i = 1; $i <= $config->pn; $i++) { // 翻页 $page->evaluate(JsFunction::createWithBody("return Promise.resolve(window.scrollTo(0, i*768));") ->scope(['i' => $i, 'height' => 768])); $page->waitFor(500); // 翻页后延迟0.5秒; } $html = $page->content(); $browser->close(); return $html; }, $options); } } catch (Exception $e){ $ql->setHtml(''); // http error } $ql->encoding('UTF-8'); if ($config->remove_head == 2) { $ql->removeHead(); } return $ql; } private function _QlInstance(){ $ql = QueryList::getInstance(); $ql->use([AbsoluteUrl::class, DownloadImage::class, GetTransCoding::class]); $ql->bind('getDataAndRelease', function () { // 获取数据,释放内存 $data = $this->getData(); // $this->destruct(); // 不销毁ql对象,仅销毁phpQuery Documents占用内存 // TODO: 升级ql后续要改动 $this->destructDocuments(); return $data->toArray(); }); $ql->bind('special', function ($config){ if (strstr($config->url, 'www.jianshu.com')) { $this->find('.image-container-fill')->remove(); } /* if (strstr($config->url, 'mp.weixin.qq.com')) { $this->find('.video_iframe')->map(function($iframe) use ($config){ $iframeSrc = $iframe->attr($config->src); if (!$iframeSrc){ return ; } $iframeSrc = preg_replace('/(width|height)=([^&]*)/i', '', $iframeSrc); $iframe->attr('src', str_replace('&&', '&', $iframeSrc)); return $iframe; }); }*/ return $this; }); return $ql; } /** * @param $article * @param $option * @return mixed */ protected function insert_article($article, $option){ if (isset($option['url'])) { $info = $this->checkPostLink($option['url']); }else{ $info = []; } if (empty($article) | empty($article['title']) | empty($article['content'])) { if (count($info)) { $this->wpdb->update($this->table_post, ['status'=>5,'Message'=>"文章已被删除或者文章格式不正确"],["id"=>$info[0]["id"]]); } return $this->format($article, '内容错误, 出现这个错误是 title 或者 content是空的没获取到。 首先请确保使用debugging的时候是正常的, 可能出现的问题有:目标站有防采集策略、请求频率限制、js跳转拦截策略、或者其他防采集策略, 如果是列表/分页采集、前面一些数据是正常的,后面的出现内容错误,极有可能是命中了访问频率限制策略或js跳转策略。'); } if (!empty($option['collect_custom_content'])){ $stdClass = json_decode($option['collect_custom_content'], true); $stdClass['head'] = htmlspecialchars_decode($stdClass['head'], ENT_QUOTES); $stdClass['foot'] = htmlspecialchars_decode($stdClass['foot'], ENT_QUOTES); $stdClass = str_replace( ['{link}', '{title}', '{title+link}', '{author}', '{name}'], [$article['link'], $article['title'], '' . $article['title'] . '', (isset($article['author']) ? $article['author'] : ''), (isset($article['name']) ? $article['name'] : '')], $stdClass); if (!empty($stdClass['head'])) $article['content'] = $stdClass['head'] . $article['content'] ; if (!empty($stdClass['foot'])) $article['content'] = $article['content'] . $stdClass['foot'] ; } $data['status'] = 2; $data['option_id'] = $option['id']; $data['cover'] = isset($article['image']) ? $article['image'] : ''; $data['link'] = $article['link']; $data['title'] = mb_substr($this->text_keyword_replace($article['title'], $option), 0, 120); $data['content'] = $this->text_keyword_replace($article['content'], $option); $insertKeyword = get_option(FRC_Validation::FRC_VALIDATION_INSERT_KEYWORD); if (!empty($insertKeyword) && json_decode($insertKeyword)->switch == 'open') { $data['content'] = $this->insertKeywords($data['content'], $option); } $data['message'] = 'Success.'; $data['created_at'] = current_time('mysql'); $data['updated_at'] = current_time('mysql'); if (empty($info)) $info = $this->checkPostLink($article['link']); if (count($info)) { if ($info[0]["status"] == 1) { if ($this->wpdb->update($this->table_post, $data,["id"=>$info[0]["id"]])){ return $this->format($article, '采集完成'); } }else{ return $this->format($article, '入库失败、可能此条数据已经在数据库中存在了'); } } if ($this->wpdb->insert($this->table_post, $data)){ return $this->format($article, '采集完成'); } } /** * @param $txt * @param $option * @return string */ protected function insertKeywords($txt, $option){ if (empty($option['collect_keywords'])){ return $txt; } $keywords = json_decode($option['collect_keywords']); if (empty($keywords)){ return $txt; } $items = []; foreach ($keywords as $keyword){ for ($i=0; $i<$keyword->count; $i++){ if (isset($keyword->link)){ $item = sprintf('%s', $keyword->link, $keyword->title); } else { $item = $keyword->title; } array_push($items, $item); } } return randomInsertString($txt, $items); } /** * @param $link * @return array|null|object */ protected function checkPostLink($link){ return $this->wpdb->get_results( $this->wpdb->prepare("select `id`,`status`,`link` from $this->table_post where `link` = %s", $link), ARRAY_A ); } /** * @param $rules * @return array */ private function rulesFormat($rules) { if (empty($rules)){ return ''; } $resRule = []; collect( explode(")(", $rules) )->map(function ($item) use (&$resRule){ list($key, $value) = explode("%", $item); list($label, $rule, $filter) = explode("|", $value); $label == 'null' && $label = null; $rule == 'null' && $rule = null; $filter == 'null' && $filter = null; $resRule[$key] = [$label, $rule, $filter]; }); return $resRule; } public function response($error, $data = [], $msg = 'ok'){ return [ '胖鼠采集' => '欢迎使用胖鼠采集调试功能.', 'code' => $error, 'msg' => $msg, 'data' => $data ]; /* $frc_validation_sponsorship = get_option(FRC_Validation::FRC_VALIDATION_SPONSORSHIP); if ($frc_validation_sponsorship === 'sponsorship'){ return [ 'code' => $error, '胖鼠' => FRC_Validation::FRC_HINT_D, 'msg' => $msg, 'data' => $data ]; } if (time() - get_option(FRC_Validation::FRC_INSERT_TIME) < 86400){ return [ 'code' => $error, 'msg' => $msg, 'data' => $data ]; } $frc_validation_debug_count = get_option(FRC_Validation::FRC_VALIDATION_DEBUG_COUNT, '0'); if ($frc_validation_debug_count === '0'){ return array_merge(FRC_Validation::FRC_DEBUG_INFO_PROMPT, [ 'code' => $error, 'msg' => $msg ]); } $remaining = $frc_validation_debug_count-1; update_option(FRC_Validation::FRC_VALIDATION_DEBUG_COUNT, $remaining); return [ 'code' => $error, '胖鼠' => sprintf(FRC_Validation::FRC_HINT_E, $remaining), 'msg' => $msg, 'data' => $data ];*/ } /** * @param $article * @param string $msg * @return mixed */ protected function format($article, $msg = ''){ $article['message'] = $msg; $article['content'] = !empty($article['content']) ? mb_substr($article['content'], 0, 100).'.....' : ''; return $article; } /** * @param $time * @return bool */ private function checkWechatHistoryTimeLimit($time) { $toDay = get_option("fat_rat_collect_wechat_history_time_" . date("Y-m-d")); if (!$toDay) { $toDayTime = $time; }else{ $toDayTime = $toDay + $time; } if ($toDayTime > 500) return false; update_option("fat_rat_collect_wechat_history_time_" . date("Y-m-d"), $toDayTime); return true; } } function frc_spider() { if (!frc_mysql_upgrade()){ return ; } frc_front_loading(); $frc_options = new FRC_Options(); $options = collect($frc_options->options())->reverse()->groupBy('collect_type'); // TODO:首页拆分。优化速度。 ?>配置规则
![]()
欢迎你使用胖鼠创建自己的规则, 如果第一次遇见认识胖鼠. 点这里
配置名称: value="" placeholder="我的第一个胖鼠采集规则"/>* 一句话的描述: 配置类型: value="list" > 列表采集配置 > 详情采集配置 > 全站采集 全站采集: 采集范围处写全站正则, 参考
全站采集: 采集规则处不填
列表可直接写采集地址. 详情只写规则, 采集地址在使用的时候填写即可.
采集方式: > 静态渲染 > 动态渲染 静态渲染: 普通页面, 动态渲染: ajax页面
编码处理: > 自动识别(推荐) > 删HEAD(非UTF-8编码推荐) > 强制转换(终极方案) 此功能用于解决乱码问题,自动识别转码失败你可尝试删HEAD,强制转换,选的不对有可能会取不到数据哦.
图片下载: > 下载到本地(推荐) > 不下载 > 删除图片 > 图片下载不入媒体库 「经典速度」 下载到本地: 可安装云存储插件对接云存储
「高速采集」 不下载: 使用源站图片路径, 如果源站图片路径是相对路径, 会把地址补全
「超超高速采集」删除图片: 删除正文所有<\img >
「经典速度」 图片下载不入媒体库: 图片已经下载, 但是不上传到媒体库中「发布文章速度: 超快」
图片路径: > 绝对路径(OSS/云存储必选) > 相对路径(本地存储图片) 绝对路径格式: https://www.xxx.com/wp-content/uploads/2020/05/A.jpg
相对路径格式: /wp-content/uploads/2020/05/A.jpg
采集地址: * 小提示: 不清楚下面的规则怎么写? 去试试debug功能吧 ~
分页采集地址: 把页码的码数替换为 {page} 注: 非列表采集不填
例子: https://xx.qq.com/webplat/info/news_version3/154/2233/3889/m2702/list_{page}.shtml
采集范围: * 填写Html标签的 class 或者 id (Jquery语法) 采集范围参考
采集规则: 规则名 - JQuery选择器 - 属性 - 内容过滤: 空格分割 Jquery手册
---*列表页 我们只取详情页的url链接即可
详情页面采集区域: * 填写Html标签的 class 或者 id (Jquery语法) 参考
详情页面采集规则: 规则名 - JQuery选择器 - 属性 - 内容过滤: 空格分割 Jquery手册
---*
---*
---详情页,我们只拿 Title Content 一片文章岂不是就有了. 其他字段如 日期/作者 回头考虑怎么开放给大家用..
Paging字段为详情页内容分页采集功能, 细节用法参考官网文档
cookie: 不需要登陆就可采集的不用填写,cookie可能需要根据不同网站不同需要定时更新。
图片源属性: 默认即可。某些站点图片是使用 Js 异步加载。此选项用来设置真实图片地址的属性。
内容插入: 插入文章开头
插入文章结尾
可使用的变量: {title} | {link} | {title+link} 参考
关键词替换 注: 阿拉伯数字1 2 3 和 英文字符 a b c 不可以配置替换. 可能会把内容图片URL替换成错误的. 别乱搞哦
关键词随机插入 带*号必填且不可错误的
'2.0.0'){ //2.0以上版本不需要数据库升级 return true; } $option = get_option('frc_mysql_upgrade'); if ($option == 'upgrade complete'){ return true; } $last_id = get_option('frc_mysql_upgrade_progress', 0); ?>
![]()
![]()
announcement('notice-home')); ?>
微信文章地址 小提示: 如需要内容过滤需求 如删除: 第一张图片 or 第二个p标签 or 倒数第三张图片 等需求 请使用内容过滤功能
例: -img:gt(-4) 过滤文章底部倒数3张图片! -img:eq(1) 只过滤文章正文第2张图片 (程序从0开始)
简书文章地址 Tips: 简书默认规则过滤了a标签, 一定要了解a与-a的区别哦、 你们可以在配置中心查看胖鼠写的配置
知乎(问答)地址 Tips: 此规则是采集知乎问答页面, 不是知乎文章详情页
可使用F12调试模式、查看采集结果哦
'); _e("亲爱的皮皮虾: 目前没有任何一个列表配置。皮皮虾我们走
"); } else { ?>
列表爬虫(点击采集)
{$option['collect_name']}"); } ?> getAppreciatesHtml(7)); ?>'); _e("亲爱的毛毛虫: 目前没有任何一个分页配置。毛毛虫我们走
"); } else { ?>
选择页面的规则配置 '; foreach ($option_list as $option) { $string .= ''; } $string .= ''; _e($string); ?> 配置创建在 新建配置->配置类型=列表
采集页码/翻页 页码用 - 隔开 例: 2-10 采集2->10页
动态渲染页面是向下翻页几次 例: 3 向下翻页三次, 翻页高度768px
getAppreciatesHtml(7)); ?> '); _e("亲爱的皮皮: 目前没有任何一个详情配置。胖鼠我们走
"); } else { ?>
详情地址 详情配套配置 '; foreach ($options['single'] as $option) { if (in_array($option['collect_name'], FRC_ApiError::BUTTON_DISABLED)){ $string .= ''; } else { $string .= ''; } } $string .= ''; _e($string); ?> 配置创建在 新建配置->配置类型=详情
getAppreciatesHtml(7)); ?> '); _e("亲爱的胖球: 目前没有任何一个全站采集配置。兔子我们走
"); } else { ?>
全站采集
{$option['collect_name']}"); } ?>
使用文档: 微信公众平台cookie: 此处粘贴F12控制台网络请求过滤
https://mp.weixin.qq.com/cgi-bin/appmsgpublish 获取此次请求的请求头中的cookie微信公众平台token: 打开微信公众平台后,F12打开控制台console执行
console.log( new URLSearchParams(window.location.search).get("token")) 后粘贴结果微信公众号名称: 小提示: 请确认全称无误
起始页数(从哪页开始采): 采集页数(采集多少页): 小提示:
一页为20次文章发布(每次文章发布包含多次文章)
目前单次最多可采集30页,单日最大可采集500页
声明: 为避免公众号被封禁,此功能已进行频率控制,请避免频繁使用。
如需大批量采集,建议有条件的用户准备多个微信公众号参数并进行轮换使用,以规避频繁调用风险。
其他选择是申请几个空白公众号专用于接口调用(无需备案或其他花费)。
功能用于学习交流,对于因不当使用此功能而导致的账号封禁,请自行负责
鼠友你好吖, 欢迎来到胖鼠采集v2.0的新世界
此次大版本更新, 耗时无数夜晚, 重写了胖鼠采集底层
接下来请进行数据库迁移升级, 如遇到问题请到群内寻找帮助
(①)点我迁移升级采集配置')); } elseif ($option == '2') { _e(sprintf('')); _e(sprintf('大数据量用户会进行分段数据迁移,每次迁移500条,目前数据库迁移进度%s
', $last_id)); } else { update_option('frc_mysql_upgrade', 'upgrade complete'); _e('升级已结束
'); } ?>过程可能过长, 请耐心等待.
notice(); (new FRC_Validation())->report_permissions(); } ================================================ FILE: includes/fatrat-validation.php ================================================ [self::FRC_VALIDATION_AUTO_TAGS, '2'], 'inner-chain' => [self::FRC_VALIDATION_INNER_CHAIN, '2'], 'featured-picture' => [self::FRC_VALIDATION_FEATURED_PICTURE, '2'], 'dynamic-fields' => [self::FRC_VALIDATION_DYNAMIC_FIELDS, '2'], 'all-collect' => [self::FRC_VALIDATION_ALL_COLLECT, '1'], 'rendering' => [self::FRC_VALIDATION_RENDERING, '1'], 'automatic-save-pic' => [self::FRC_VALIDATION_AUTOMATIC_SAVE_PIC, '1'], 'sponsorship' => [self::FRC_VALIDATION_SPONSORSHIP, 'sponsorship'], 'release-control' => [self::FRC_VALIDATION_RELEASE_CONTROL, '1'], 'insert-keyword' => [self::FRC_VALIDATION_INSERT_KEYWORD, '2'], 'wechat-history' => [self::FRC_VALIDATION_WECHAT_HISTORY, '1'], ]; const FRC_HINT_A = '感谢鼠友%s的赞助, %s为您充值%s次, 您剩余 %s 次'; const FRC_HINT_B = '咣咣咣, 人品大爆发, 感谢鼠友%s为您带来翻倍奖励, %s本次为您充值%s次, 您剩余 %s 次'; const FRC_HINT_C = '赞助鼠半小时只能为您支持一次哦.'; const FRC_HINT_D = '鼠友你好, 感谢您的赞助支持, 胖鼠采集因您更美好.'; const FRC_HINT_E = 'debugging功能剩余次数(%s)次'; const FRC_HINT_F = '分页采集占用系统资源, 单次采集页数不可大于3页, 赞助鼠友可以无限制哦'; const FRC_HINT_G = '操作状态成功le.'; const FRC_HINT_H = '您的debugging剩余次数太多了, 无需充值.'; const FRC_HINT_J = '插件的发展需要您的支持, 感谢赞助.'; const FRC_HINT_K = '网络连接失败, 请求超时, 如异常持续, 请联系胖鼠排查原因!'; const FRC_HINT_L = '保存完成, 已设置默认发布选项, 如需自定义发布选项 请赞助支持, 开源不易感谢支持.'; const FRC_HINT_Z = '非赞助鼠友最多可创建5个配置哦, 开源不易感谢支持'; const FRC_HINT_M = '当前登陆的WordPress账号无操作权限,请使用后台管理员账号进行操作.'; private $shutdownJson; private $openJson; public function __construct() { $this->shutdownJson = json_encode(['switch' => 'shutdown', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql')]); $this->openJson = json_encode(['switch' => 'open', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql')]); } public function validation_function_switch(){ if ($this->update_switch(self::FRC_VALIDATION_ABILITY_MAP[frc_sanitize_text('switch_action')][0])){ return ['code' => FRC_ApiError::SUCCESS, 'msg' => self::FRC_HINT_G]; } else { return ['code' => FRC_ApiError::FAIL, 'msg' => 'Fail.']; } } public function validation_activation(){ $action = frc_sanitize_text('activation_action'); $data = $this->validation_request('/validation', ['action' => $action], 5); if (isset($data)) { $data = json_decode($data); if (!$this->checkAccessToken($data)){ return ['code' => FRC_ApiError::ERR_TOKEN, 'msg' => FRC_ApiError::msg(FRC_ApiError::ERR_TOKEN)]; } if ($data->code == self::FRC_API_CODE) { $config = self::FRC_VALIDATION_ABILITY_MAP[$action]; switch ($config[1]){ case '1': $config[1] = $this->openJson; break; case '2': $config[1] = $this->shutdownJson; break; } if ($data->data) { $config[1] = collect(json_decode($config[1],true))->merge($data->data)->toJson(); } $result = add_option($config[0], $config[1]); if (!$result){ $result = update_option($config[0], $config[1]); } return ['code' => FRC_ApiError::SUCCESS, 'msg' => $data->msg, 'data' => $result]; } else { return ['code' => FRC_ApiError::NO_PERMISSION, 'msg' => isset($data->msg) ? $data->msg : '验证失败.']; } } else { return ['code' => FRC_ApiError::CHECK_SERVER_FAIL, 'msg' => '网络错误, 请重试. ']; } } protected function update_switch($action){ $result = get_option($action); if (empty($result)){ return false; } $option = json_decode($result, true); $option['switch'] = ($option['switch'] == 'open') ? 'shutdown' : 'open'; return update_option($action, json_encode($option)); } public function validation_correction(){ foreach (self::FRC_VALIDATION_ABILITY_MAP as $item){ delete_option($item[0]); } delete_option('frc_cron_release'); delete_option('frc_cron_spider'); } public function notice(){ try{ $notice = $this->validation_request_static('/static/notice.json'); update_option(self::FRC_VALIDATION_NOTICE, $notice); } catch (\GuzzleHttp\Exception\RequestException $e){ delete_option(self::FRC_VALIDATION_NOTICE); } } public function announcement($location = 'notice-home'){ try{ $notice = get_option(self::FRC_VALIDATION_NOTICE); $notice = json_decode($notice); if (isset($notice->$location)){ if ($notice->$location->type == 'link'){ return sprintf($notice->$location->string, ''.$notice->$location->title.''); } else { return $notice->$location->string; } } } catch (\GuzzleHttp\Exception\RequestException $e){ return ''; } return ''; } public function report_permissions() { $report_time = get_option('frc_report_permissions_time', time()-10); if ( time() < $report_time ){ return ; } $permissions = array('power' => [], 'other' => []); collect(self::FRC_VALIDATION_ABILITY_MAP)->map(function ($permission, $key) use (&$permissions){ $permissions['power'][$key] = (get_option($permission[0], null)? 'open' : 'null'); }); $data = $this->validation_request('/validation/report', ['permissions' => serialize($permissions)], 1); if (isset($data)) { $data = json_decode($data); if ($data->code == self::FRC_API_CODE && $this->checkAccessToken($data)) { update_option('frc_report_permissions_time', strtotime('+10day')); return; } elseif ($data->code == self::FRC_API_CODE_PERMISSIONS && $this->checkAccessToken($data)) { foreach ($data->data->power as $permission => $val){ if ($val === 'abnormal'){ delete_option(self::FRC_VALIDATION_ABILITY_MAP[$permission][0]); } } update_option('frc_report_permissions_time', strtotime('+5hours')); } else { update_option('frc_report_permissions_time', strtotime('+3day')); } } return ; } public function getAppreciatesHtml($count = 5){ $html = ''; return $html; } public function appreciates($count = null){ $notice = get_option(self::FRC_VALIDATION_NOTICE); $notice = json_decode($notice); if (isset($notice->appreciates)){ if ($count === null){ return $notice->appreciates; } shuffle($notice->appreciates); return array_slice($notice->appreciates, 0, $count); } return []; } private function checkAccessToken($data){ return true; // return ($data->token === md5(parse_url($this->url)['host'].date('Y-m-d ?:i').$data->code.$data->msg)); } private function getAccessToken(){ return md5(date('Y-m-d ?:i').site_url()); } private function validation_request_static($path, $timeout = 1){ return (new \GuzzleHttp\Client())->request('get', $this->url.$path, ['verify' => false, 'connect_timeout' => $timeout])->getBody()->getContents(); } private function validation_request($uri, $query = [], $timeout = 1){ try{ $query['host'] = site_url(); $query['token'] = $this->getAccessToken(); $query['version'] = get_option('frc_db_version'); $http = (new \GuzzleHttp\Client())->request('post', $this->url.'/api'.$uri, ['verify' => false, 'connect_timeout' => $timeout, 'form_params' => $query]); update_option('fat_rat_collect_api_code', $http->getStatusCode()); return $http->getBody()->getContents(); } catch (Exception $e) { update_option('fat_rat_collect_api_code', $e->getCode()); return null; } } } ================================================ FILE: public/css/bootstrap.css ================================================ @charset "UTF-8"; /*! * Bootstrap v5.0.2 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); } *, *::before, *::after { box-sizing: border-box; } @media (prefers-reduced-motion: no-preference) { :root { scroll-behavior: smooth; } } body { margin: 0; font-family: var(--bs-font-sans-serif); font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } hr { margin: 1rem 0; color: inherit; background-color: currentColor; border: 0; opacity: 0.25; } hr:not([size]) { height: 1px; } h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; line-height: 1.2; } h1, .h1 { font-size: calc(1.375rem + 1.5vw); } @media (min-width: 1200px) { h1, .h1 { font-size: 2.5rem; } } h2, .h2 { font-size: calc(1.325rem + 0.9vw); } @media (min-width: 1200px) { h2, .h2 { font-size: 2rem; } } h3, .h3 { font-size: calc(1.3rem + 0.6vw); } @media (min-width: 1200px) { h3, .h3 { font-size: 1.75rem; } } h4, .h4 { font-size: calc(1.275rem + 0.3vw); } @media (min-width: 1200px) { h4, .h4 { font-size: 1.5rem; } } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-bs-original-title] { -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul { padding-left: 2rem; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: 0.5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small, .small { font-size: 0.875em; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } sub, sup { position: relative; font-size: 0.75em; line-height: 0; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } a { color: #0d6efd; text-decoration: underline; } a:hover { color: #0a58ca; } a:not([href]):not([class]), a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: var(--bs-font-monospace); font-size: 1em; direction: ltr /* rtl:ignore */; unicode-bidi: bidi-override; } pre { display: block; margin-top: 0; margin-bottom: 1rem; overflow: auto; font-size: 0.875em; } pre code { font-size: inherit; color: inherit; word-break: normal; } code { font-size: 0.875em; color: #d63384; word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.2rem 0.4rem; font-size: 0.875em; color: #fff; background-color: #212529; border-radius: 0.2rem; } kbd kbd { padding: 0; font-size: 1em; font-weight: 700; } figure { margin: 0 0 1rem; } img, svg { vertical-align: middle; } table { caption-side: bottom; border-collapse: collapse; } caption { padding-top: 0.5rem; padding-bottom: 0.5rem; color: #6c757d; text-align: left; } th { text-align: inherit; text-align: -webkit-match-parent; } thead, tbody, tfoot, tr, td, th { border-color: inherit; border-style: solid; border-width: 0; } label { display: inline-block; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, select { text-transform: none; } [role=button] { cursor: pointer; } select { word-wrap: normal; } select:disabled { opacity: 1; } [list]::-webkit-calendar-picker-indicator { display: none; } button, [type=button], [type=reset], [type=submit] { -webkit-appearance: button; } button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled) { cursor: pointer; } ::-moz-focus-inner { padding: 0; border-style: none; } textarea { resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { float: left; width: 100%; padding: 0; margin-bottom: 0.5rem; font-size: calc(1.275rem + 0.3vw); line-height: inherit; } @media (min-width: 1200px) { legend { font-size: 1.5rem; } } legend + * { clear: left; } ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-text, ::-webkit-datetime-edit-minute, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-year-field { padding: 0; } ::-webkit-inner-spin-button { height: auto; } [type=search] { outline-offset: -2px; -webkit-appearance: textfield; } /* rtl:raw: [type="tel"], [type="url"], [type="email"], [type="number"] { direction: ltr; } */ ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-color-swatch-wrapper { padding: 0; } ::file-selector-button { font: inherit; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } iframe { border: 0; } summary { display: list-item; cursor: pointer; } progress { vertical-align: baseline; } [hidden] { display: none !important; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: calc(1.625rem + 4.5vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-1 { font-size: 5rem; } } .display-2 { font-size: calc(1.575rem + 3.9vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-2 { font-size: 4.5rem; } } .display-3 { font-size: calc(1.525rem + 3.3vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-3 { font-size: 4rem; } } .display-4 { font-size: calc(1.475rem + 2.7vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-4 { font-size: 3.5rem; } } .display-5 { font-size: calc(1.425rem + 2.1vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-5 { font-size: 3rem; } } .display-6 { font-size: calc(1.375rem + 1.5vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-6 { font-size: 2.5rem; } } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 0.5rem; } .initialism { font-size: 0.875em; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote > :last-child { margin-bottom: 0; } .blockquote-footer { margin-top: -1rem; margin-bottom: 1rem; font-size: 0.875em; color: #6c757d; } .blockquote-footer::before { content: "— "; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; border-radius: 0.25rem; max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 0.875em; color: #6c757d; } .container, .container-fluid, .container-xxl, .container-xl, .container-lg, .container-md, .container-sm { width: 100%; padding-right: var(--bs-gutter-x, 0.75rem); padding-left: var(--bs-gutter-x, 0.75rem); margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container-sm, .container { max-width: 540px; } } @media (min-width: 768px) { .container-md, .container-sm, .container { max-width: 720px; } } @media (min-width: 992px) { .container-lg, .container-md, .container-sm, .container { max-width: 960px; } } @media (min-width: 1200px) { .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1140px; } } @media (min-width: 1400px) { .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1320px; } } .row { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; display: flex; flex-wrap: wrap; margin-top: calc(var(--bs-gutter-y) * -1); margin-right: calc(var(--bs-gutter-x) * -.5); margin-left: calc(var(--bs-gutter-x) * -.5); } .row > * { flex-shrink: 0; width: 100%; max-width: 100%; padding-right: calc(var(--bs-gutter-x) * .5); padding-left: calc(var(--bs-gutter-x) * .5); margin-top: var(--bs-gutter-y); } .col { flex: 1 0 0%; } .row-cols-auto > * { flex: 0 0 auto; width: auto; } .row-cols-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-6 > * { flex: 0 0 auto; width: 16.6666666667%; } @media (min-width: 576px) { .col-sm { flex: 1 0 0%; } .row-cols-sm-auto > * { flex: 0 0 auto; width: auto; } .row-cols-sm-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-sm-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-sm-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-sm-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-sm-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-sm-6 > * { flex: 0 0 auto; width: 16.6666666667%; } } @media (min-width: 768px) { .col-md { flex: 1 0 0%; } .row-cols-md-auto > * { flex: 0 0 auto; width: auto; } .row-cols-md-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-md-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-md-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-md-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-md-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-md-6 > * { flex: 0 0 auto; width: 16.6666666667%; } } @media (min-width: 992px) { .col-lg { flex: 1 0 0%; } .row-cols-lg-auto > * { flex: 0 0 auto; width: auto; } .row-cols-lg-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-lg-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-lg-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-lg-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-lg-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-lg-6 > * { flex: 0 0 auto; width: 16.6666666667%; } } @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; } .row-cols-xl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } } @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; } .row-cols-xxl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xxl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xxl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xxl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xxl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xxl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xxl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } } .col-auto { flex: 0 0 auto; width: auto; } .col-1 { flex: 0 0 auto; width: 8.33333333%; } .col-2 { flex: 0 0 auto; width: 16.66666667%; } .col-3 { flex: 0 0 auto; width: 25%; } .col-4 { flex: 0 0 auto; width: 33.33333333%; } .col-5 { flex: 0 0 auto; width: 41.66666667%; } .col-6 { flex: 0 0 auto; width: 50%; } .col-7 { flex: 0 0 auto; width: 58.33333333%; } .col-8 { flex: 0 0 auto; width: 66.66666667%; } .col-9 { flex: 0 0 auto; width: 75%; } .col-10 { flex: 0 0 auto; width: 83.33333333%; } .col-11 { flex: 0 0 auto; width: 91.66666667%; } .col-12 { flex: 0 0 auto; width: 100%; } .offset-1 { margin-left: 8.33333333%; } .offset-2 { margin-left: 16.66666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.33333333%; } .offset-5 { margin-left: 41.66666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.33333333%; } .offset-8 { margin-left: 66.66666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.33333333%; } .offset-11 { margin-left: 91.66666667%; } .g-0, .gx-0 { --bs-gutter-x: 0; } .g-0, .gy-0 { --bs-gutter-y: 0; } .g-1, .gx-1 { --bs-gutter-x: 0.25rem; } .g-1, .gy-1 { --bs-gutter-y: 0.25rem; } .g-2, .gx-2 { --bs-gutter-x: 0.5rem; } .g-2, .gy-2 { --bs-gutter-y: 0.5rem; } .g-3, .gx-3 { --bs-gutter-x: 1rem; } .g-3, .gy-3 { --bs-gutter-y: 1rem; } .g-4, .gx-4 { --bs-gutter-x: 1.5rem; } .g-4, .gy-4 { --bs-gutter-y: 1.5rem; } .g-5, .gx-5 { --bs-gutter-x: 3rem; } .g-5, .gy-5 { --bs-gutter-y: 3rem; } @media (min-width: 576px) { .col-sm-auto { flex: 0 0 auto; width: auto; } .col-sm-1 { flex: 0 0 auto; width: 8.33333333%; } .col-sm-2 { flex: 0 0 auto; width: 16.66666667%; } .col-sm-3 { flex: 0 0 auto; width: 25%; } .col-sm-4 { flex: 0 0 auto; width: 33.33333333%; } .col-sm-5 { flex: 0 0 auto; width: 41.66666667%; } .col-sm-6 { flex: 0 0 auto; width: 50%; } .col-sm-7 { flex: 0 0 auto; width: 58.33333333%; } .col-sm-8 { flex: 0 0 auto; width: 66.66666667%; } .col-sm-9 { flex: 0 0 auto; width: 75%; } .col-sm-10 { flex: 0 0 auto; width: 83.33333333%; } .col-sm-11 { flex: 0 0 auto; width: 91.66666667%; } .col-sm-12 { flex: 0 0 auto; width: 100%; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.33333333%; } .offset-sm-2 { margin-left: 16.66666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.33333333%; } .offset-sm-5 { margin-left: 41.66666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.33333333%; } .offset-sm-8 { margin-left: 66.66666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.33333333%; } .offset-sm-11 { margin-left: 91.66666667%; } .g-sm-0, .gx-sm-0 { --bs-gutter-x: 0; } .g-sm-0, .gy-sm-0 { --bs-gutter-y: 0; } .g-sm-1, .gx-sm-1 { --bs-gutter-x: 0.25rem; } .g-sm-1, .gy-sm-1 { --bs-gutter-y: 0.25rem; } .g-sm-2, .gx-sm-2 { --bs-gutter-x: 0.5rem; } .g-sm-2, .gy-sm-2 { --bs-gutter-y: 0.5rem; } .g-sm-3, .gx-sm-3 { --bs-gutter-x: 1rem; } .g-sm-3, .gy-sm-3 { --bs-gutter-y: 1rem; } .g-sm-4, .gx-sm-4 { --bs-gutter-x: 1.5rem; } .g-sm-4, .gy-sm-4 { --bs-gutter-y: 1.5rem; } .g-sm-5, .gx-sm-5 { --bs-gutter-x: 3rem; } .g-sm-5, .gy-sm-5 { --bs-gutter-y: 3rem; } } @media (min-width: 768px) { .col-md-auto { flex: 0 0 auto; width: auto; } .col-md-1 { flex: 0 0 auto; width: 8.33333333%; } .col-md-2 { flex: 0 0 auto; width: 16.66666667%; } .col-md-3 { flex: 0 0 auto; width: 25%; } .col-md-4 { flex: 0 0 auto; width: 33.33333333%; } .col-md-5 { flex: 0 0 auto; width: 41.66666667%; } .col-md-6 { flex: 0 0 auto; width: 50%; } .col-md-7 { flex: 0 0 auto; width: 58.33333333%; } .col-md-8 { flex: 0 0 auto; width: 66.66666667%; } .col-md-9 { flex: 0 0 auto; width: 75%; } .col-md-10 { flex: 0 0 auto; width: 83.33333333%; } .col-md-11 { flex: 0 0 auto; width: 91.66666667%; } .col-md-12 { flex: 0 0 auto; width: 100%; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.33333333%; } .offset-md-2 { margin-left: 16.66666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.33333333%; } .offset-md-5 { margin-left: 41.66666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.33333333%; } .offset-md-8 { margin-left: 66.66666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.33333333%; } .offset-md-11 { margin-left: 91.66666667%; } .g-md-0, .gx-md-0 { --bs-gutter-x: 0; } .g-md-0, .gy-md-0 { --bs-gutter-y: 0; } .g-md-1, .gx-md-1 { --bs-gutter-x: 0.25rem; } .g-md-1, .gy-md-1 { --bs-gutter-y: 0.25rem; } .g-md-2, .gx-md-2 { --bs-gutter-x: 0.5rem; } .g-md-2, .gy-md-2 { --bs-gutter-y: 0.5rem; } .g-md-3, .gx-md-3 { --bs-gutter-x: 1rem; } .g-md-3, .gy-md-3 { --bs-gutter-y: 1rem; } .g-md-4, .gx-md-4 { --bs-gutter-x: 1.5rem; } .g-md-4, .gy-md-4 { --bs-gutter-y: 1.5rem; } .g-md-5, .gx-md-5 { --bs-gutter-x: 3rem; } .g-md-5, .gy-md-5 { --bs-gutter-y: 3rem; } } @media (min-width: 992px) { .col-lg-auto { flex: 0 0 auto; width: auto; } .col-lg-1 { flex: 0 0 auto; width: 8.33333333%; } .col-lg-2 { flex: 0 0 auto; width: 16.66666667%; } .col-lg-3 { flex: 0 0 auto; width: 25%; } .col-lg-4 { flex: 0 0 auto; width: 33.33333333%; } .col-lg-5 { flex: 0 0 auto; width: 41.66666667%; } .col-lg-6 { flex: 0 0 auto; width: 50%; } .col-lg-7 { flex: 0 0 auto; width: 58.33333333%; } .col-lg-8 { flex: 0 0 auto; width: 66.66666667%; } .col-lg-9 { flex: 0 0 auto; width: 75%; } .col-lg-10 { flex: 0 0 auto; width: 83.33333333%; } .col-lg-11 { flex: 0 0 auto; width: 91.66666667%; } .col-lg-12 { flex: 0 0 auto; width: 100%; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.33333333%; } .offset-lg-2 { margin-left: 16.66666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.33333333%; } .offset-lg-5 { margin-left: 41.66666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.33333333%; } .offset-lg-8 { margin-left: 66.66666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.33333333%; } .offset-lg-11 { margin-left: 91.66666667%; } .g-lg-0, .gx-lg-0 { --bs-gutter-x: 0; } .g-lg-0, .gy-lg-0 { --bs-gutter-y: 0; } .g-lg-1, .gx-lg-1 { --bs-gutter-x: 0.25rem; } .g-lg-1, .gy-lg-1 { --bs-gutter-y: 0.25rem; } .g-lg-2, .gx-lg-2 { --bs-gutter-x: 0.5rem; } .g-lg-2, .gy-lg-2 { --bs-gutter-y: 0.5rem; } .g-lg-3, .gx-lg-3 { --bs-gutter-x: 1rem; } .g-lg-3, .gy-lg-3 { --bs-gutter-y: 1rem; } .g-lg-4, .gx-lg-4 { --bs-gutter-x: 1.5rem; } .g-lg-4, .gy-lg-4 { --bs-gutter-y: 1.5rem; } .g-lg-5, .gx-lg-5 { --bs-gutter-x: 3rem; } .g-lg-5, .gy-lg-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1200px) { .col-xl-auto { flex: 0 0 auto; width: auto; } .col-xl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xl-3 { flex: 0 0 auto; width: 25%; } .col-xl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xl-6 { flex: 0 0 auto; width: 50%; } .col-xl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xl-9 { flex: 0 0 auto; width: 75%; } .col-xl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xl-12 { flex: 0 0 auto; width: 100%; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.33333333%; } .offset-xl-2 { margin-left: 16.66666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.33333333%; } .offset-xl-5 { margin-left: 41.66666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.33333333%; } .offset-xl-8 { margin-left: 66.66666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.33333333%; } .offset-xl-11 { margin-left: 91.66666667%; } .g-xl-0, .gx-xl-0 { --bs-gutter-x: 0; } .g-xl-0, .gy-xl-0 { --bs-gutter-y: 0; } .g-xl-1, .gx-xl-1 { --bs-gutter-x: 0.25rem; } .g-xl-1, .gy-xl-1 { --bs-gutter-y: 0.25rem; } .g-xl-2, .gx-xl-2 { --bs-gutter-x: 0.5rem; } .g-xl-2, .gy-xl-2 { --bs-gutter-y: 0.5rem; } .g-xl-3, .gx-xl-3 { --bs-gutter-x: 1rem; } .g-xl-3, .gy-xl-3 { --bs-gutter-y: 1rem; } .g-xl-4, .gx-xl-4 { --bs-gutter-x: 1.5rem; } .g-xl-4, .gy-xl-4 { --bs-gutter-y: 1.5rem; } .g-xl-5, .gx-xl-5 { --bs-gutter-x: 3rem; } .g-xl-5, .gy-xl-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1400px) { .col-xxl-auto { flex: 0 0 auto; width: auto; } .col-xxl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xxl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xxl-3 { flex: 0 0 auto; width: 25%; } .col-xxl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xxl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xxl-6 { flex: 0 0 auto; width: 50%; } .col-xxl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xxl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xxl-9 { flex: 0 0 auto; width: 75%; } .col-xxl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xxl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xxl-12 { flex: 0 0 auto; width: 100%; } .offset-xxl-0 { margin-left: 0; } .offset-xxl-1 { margin-left: 8.33333333%; } .offset-xxl-2 { margin-left: 16.66666667%; } .offset-xxl-3 { margin-left: 25%; } .offset-xxl-4 { margin-left: 33.33333333%; } .offset-xxl-5 { margin-left: 41.66666667%; } .offset-xxl-6 { margin-left: 50%; } .offset-xxl-7 { margin-left: 58.33333333%; } .offset-xxl-8 { margin-left: 66.66666667%; } .offset-xxl-9 { margin-left: 75%; } .offset-xxl-10 { margin-left: 83.33333333%; } .offset-xxl-11 { margin-left: 91.66666667%; } .g-xxl-0, .gx-xxl-0 { --bs-gutter-x: 0; } .g-xxl-0, .gy-xxl-0 { --bs-gutter-y: 0; } .g-xxl-1, .gx-xxl-1 { --bs-gutter-x: 0.25rem; } .g-xxl-1, .gy-xxl-1 { --bs-gutter-y: 0.25rem; } .g-xxl-2, .gx-xxl-2 { --bs-gutter-x: 0.5rem; } .g-xxl-2, .gy-xxl-2 { --bs-gutter-y: 0.5rem; } .g-xxl-3, .gx-xxl-3 { --bs-gutter-x: 1rem; } .g-xxl-3, .gy-xxl-3 { --bs-gutter-y: 1rem; } .g-xxl-4, .gx-xxl-4 { --bs-gutter-x: 1.5rem; } .g-xxl-4, .gy-xxl-4 { --bs-gutter-y: 1.5rem; } .g-xxl-5, .gx-xxl-5 { --bs-gutter-x: 3rem; } .g-xxl-5, .gy-xxl-5 { --bs-gutter-y: 3rem; } } .table { --bs-table-bg: transparent; --bs-table-accent-bg: transparent; --bs-table-striped-color: #212529; --bs-table-striped-bg: rgba(0, 0, 0, 0.05); --bs-table-active-color: #212529; --bs-table-active-bg: rgba(0, 0, 0, 0.1); --bs-table-hover-color: #212529; --bs-table-hover-bg: rgba(0, 0, 0, 0.075); width: 100%; margin-bottom: 1rem; color: #212529; vertical-align: top; border-color: #dee2e6; } .table > :not(caption) > * > * { padding: 0.5rem 0.5rem; background-color: var(--bs-table-bg); border-bottom-width: 1px; box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); } .table > tbody { vertical-align: inherit; } .table > thead { vertical-align: bottom; } .table > :not(:last-child) > :last-child > * { border-bottom-color: currentColor; } .caption-top { caption-side: top; } .table-sm > :not(caption) > * > * { padding: 0.25rem 0.25rem; } .table-bordered > :not(caption) > * { border-width: 1px 0; } .table-bordered > :not(caption) > * > * { border-width: 0 1px; } .table-borderless > :not(caption) > * > * { border-bottom-width: 0; } .table-striped > tbody > tr:nth-of-type(odd) { --bs-table-accent-bg: var(--bs-table-striped-bg); color: var(--bs-table-striped-color); } .table-active { --bs-table-accent-bg: var(--bs-table-active-bg); color: var(--bs-table-active-color); } .table-hover > tbody > tr:hover { --bs-table-accent-bg: var(--bs-table-hover-bg); color: var(--bs-table-hover-color); } .table-primary { --bs-table-bg: #cfe2ff; --bs-table-striped-bg: #c5d7f2; --bs-table-striped-color: #000; --bs-table-active-bg: #bacbe6; --bs-table-active-color: #000; --bs-table-hover-bg: #bfd1ec; --bs-table-hover-color: #000; color: #000; border-color: #bacbe6; } .table-secondary { --bs-table-bg: #e2e3e5; --bs-table-striped-bg: #d7d8da; --bs-table-striped-color: #000; --bs-table-active-bg: #cbccce; --bs-table-active-color: #000; --bs-table-hover-bg: #d1d2d4; --bs-table-hover-color: #000; color: #000; border-color: #cbccce; } .table-success { --bs-table-bg: #d1e7dd; --bs-table-striped-bg: #c7dbd2; --bs-table-striped-color: #000; --bs-table-active-bg: #bcd0c7; --bs-table-active-color: #000; --bs-table-hover-bg: #c1d6cc; --bs-table-hover-color: #000; color: #000; border-color: #bcd0c7; } .table-info { --bs-table-bg: #cff4fc; --bs-table-striped-bg: #c5e8ef; --bs-table-striped-color: #000; --bs-table-active-bg: #badce3; --bs-table-active-color: #000; --bs-table-hover-bg: #bfe2e9; --bs-table-hover-color: #000; color: #000; border-color: #badce3; } .table-warning { --bs-table-bg: #fff3cd; --bs-table-striped-bg: #f2e7c3; --bs-table-striped-color: #000; --bs-table-active-bg: #e6dbb9; --bs-table-active-color: #000; --bs-table-hover-bg: #ece1be; --bs-table-hover-color: #000; color: #000; border-color: #e6dbb9; } .table-danger { --bs-table-bg: #f8d7da; --bs-table-striped-bg: #eccccf; --bs-table-striped-color: #000; --bs-table-active-bg: #dfc2c4; --bs-table-active-color: #000; --bs-table-hover-bg: #e5c7ca; --bs-table-hover-color: #000; color: #000; border-color: #dfc2c4; } .table-light { --bs-table-bg: #f8f9fa; --bs-table-striped-bg: #ecedee; --bs-table-striped-color: #000; --bs-table-active-bg: #dfe0e1; --bs-table-active-color: #000; --bs-table-hover-bg: #e5e6e7; --bs-table-hover-color: #000; color: #000; border-color: #dfe0e1; } .table-dark { --bs-table-bg: #212529; --bs-table-striped-bg: #2c3034; --bs-table-striped-color: #fff; --bs-table-active-bg: #373b3e; --bs-table-active-color: #fff; --bs-table-hover-bg: #323539; --bs-table-hover-color: #fff; color: #fff; border-color: #373b3e; } .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; } @media (max-width: 575.98px) { .table-responsive-sm { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 767.98px) { .table-responsive-md { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 991.98px) { .table-responsive-lg { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 1199.98px) { .table-responsive-xl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 1399.98px) { .table-responsive-xxl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } .form-label { margin-bottom: 0.5rem; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; } .form-text { margin-top: 0.25rem; font-size: 0.875em; color: #6c757d; } .form-control { display: block; width: 100%; padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; -webkit-appearance: none; -moz-appearance: none; appearance: none; border-radius: 0.25rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { transition: none; } } .form-control[type=file] { overflow: hidden; } .form-control[type=file]:not(:disabled):not([readonly]) { cursor: pointer; } .form-control:focus { color: #212529; background-color: #fff; border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-control::-webkit-date-and-time-value { height: 1.5em; } .form-control::-moz-placeholder { color: #6c757d; opacity: 1; } .form-control::placeholder { color: #6c757d; opacity: 1; } .form-control:disabled, .form-control[readonly] { background-color: #e9ecef; opacity: 1; } .form-control::file-selector-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; -webkit-margin-end: 0.75rem; margin-inline-end: 0.75rem; color: #212529; background-color: #e9ecef; pointer-events: none; border-color: inherit; border-style: solid; border-width: 0; border-inline-end-width: 1px; border-radius: 0; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control::file-selector-button { transition: none; } } .form-control:hover:not(:disabled):not([readonly])::file-selector-button { background-color: #dde0e3; } .form-control::-webkit-file-upload-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; -webkit-margin-end: 0.75rem; margin-inline-end: 0.75rem; color: #212529; background-color: #e9ecef; pointer-events: none; border-color: inherit; border-style: solid; border-width: 0; border-inline-end-width: 1px; border-radius: 0; -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control::-webkit-file-upload-button { -webkit-transition: none; transition: none; } } .form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { background-color: #dde0e3; } .form-control-plaintext { display: block; width: 100%; padding: 0.375rem 0; margin-bottom: 0; line-height: 1.5; color: #212529; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; } .form-control-sm { min-height: calc(1.5em + (0.5rem + 2px)); padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.2rem; } .form-control-sm::file-selector-button { padding: 0.25rem 0.5rem; margin: -0.25rem -0.5rem; -webkit-margin-end: 0.5rem; margin-inline-end: 0.5rem; } .form-control-sm::-webkit-file-upload-button { padding: 0.25rem 0.5rem; margin: -0.25rem -0.5rem; -webkit-margin-end: 0.5rem; margin-inline-end: 0.5rem; } .form-control-lg { min-height: calc(1.5em + (1rem + 2px)); padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.3rem; } .form-control-lg::file-selector-button { padding: 0.5rem 1rem; margin: -0.5rem -1rem; -webkit-margin-end: 1rem; margin-inline-end: 1rem; } .form-control-lg::-webkit-file-upload-button { padding: 0.5rem 1rem; margin: -0.5rem -1rem; -webkit-margin-end: 1rem; margin-inline-end: 1rem; } textarea.form-control { min-height: calc(1.5em + (0.75rem + 2px)); } textarea.form-control-sm { min-height: calc(1.5em + (0.5rem + 2px)); } textarea.form-control-lg { min-height: calc(1.5em + (1rem + 2px)); } .form-control-color { max-width: 3rem; height: auto; padding: 0.375rem; } .form-control-color:not(:disabled):not([readonly]) { cursor: pointer; } .form-control-color::-moz-color-swatch { height: 1.5em; border-radius: 0.25rem; } .form-control-color::-webkit-color-swatch { height: 1.5em; border-radius: 0.25rem; } .form-select { display: block; width: 100%; padding: 0.375rem 2.25rem 0.375rem 0.75rem; -moz-padding-start: calc(0.75rem - 3px); font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 16px 12px; border: 1px solid #ced4da; border-radius: 0.25rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-select { transition: none; } } .form-select:focus { border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-select[multiple], .form-select[size]:not([size="1"]) { padding-right: 0.75rem; background-image: none; } .form-select:disabled { background-color: #e9ecef; } .form-select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #212529; } .form-select-sm { padding-top: 0.25rem; padding-bottom: 0.25rem; padding-left: 0.5rem; font-size: 0.875rem; } .form-select-lg { padding-top: 0.5rem; padding-bottom: 0.5rem; padding-left: 1rem; font-size: 1.25rem; } .form-check { display: block; min-height: 1.5rem; padding-left: 1.5em; margin-bottom: 0.125rem; } .form-check .form-check-input { float: left; margin-left: -1.5em; } .form-check-input { width: 1em; height: 1em; margin-top: 0.25em; vertical-align: top; background-color: #fff; background-repeat: no-repeat; background-position: center; background-size: contain; border: 1px solid rgba(0, 0, 0, 0.25); -webkit-appearance: none; -moz-appearance: none; appearance: none; -webkit-print-color-adjust: exact; color-adjust: exact; } .form-check-input[type=checkbox] { border-radius: 0.25em; } .form-check-input[type=radio] { border-radius: 50%; } .form-check-input:active { filter: brightness(90%); } .form-check-input:focus { border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-check-input:checked { background-color: #0d6efd; border-color: #0d6efd; } .form-check-input:checked[type=checkbox] { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); } .form-check-input:checked[type=radio] { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); } .form-check-input[type=checkbox]:indeterminate { background-color: #0d6efd; border-color: #0d6efd; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); } .form-check-input:disabled { pointer-events: none; filter: none; opacity: 0.5; } .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { opacity: 0.5; } .form-switch { padding-left: 2.5em; } .form-switch .form-check-input { width: 2em; margin-left: -2.5em; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); background-position: left center; border-radius: 2em; transition: background-position 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-switch .form-check-input { transition: none; } } .form-switch .form-check-input:focus { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); } .form-switch .form-check-input:checked { background-position: right center; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); } .form-check-inline { display: inline-block; margin-right: 1rem; } .btn-check { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .btn-check[disabled] + .btn, .btn-check:disabled + .btn { pointer-events: none; filter: none; opacity: 0.65; } .form-range { width: 100%; height: 1.5rem; padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .form-range:focus { outline: 0; } .form-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-range::-moz-focus-outer { border: 0; } .form-range::-webkit-slider-thumb { width: 1rem; height: 1rem; margin-top: -0.25rem; background-color: #0d6efd; border: 0; border-radius: 1rem; -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-range::-webkit-slider-thumb { -webkit-transition: none; transition: none; } } .form-range::-webkit-slider-thumb:active { background-color: #b6d4fe; } .form-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; } .form-range::-moz-range-thumb { width: 1rem; height: 1rem; background-color: #0d6efd; border: 0; border-radius: 1rem; -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-range::-moz-range-thumb { -moz-transition: none; transition: none; } } .form-range::-moz-range-thumb:active { background-color: #b6d4fe; } .form-range::-moz-range-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; } .form-range:disabled { pointer-events: none; } .form-range:disabled::-webkit-slider-thumb { background-color: #adb5bd; } .form-range:disabled::-moz-range-thumb { background-color: #adb5bd; } .form-floating { position: relative; } .form-floating > .form-control, .form-floating > .form-select { height: calc(3.5rem + 2px); line-height: 1.25; } .form-floating > label { position: absolute; top: 0; left: 0; height: 100%; padding: 1rem 0.75rem; pointer-events: none; border: 1px solid transparent; transform-origin: 0 0; transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-floating > label { transition: none; } } .form-floating > .form-control { padding: 1rem 0.75rem; } .form-floating > .form-control::-moz-placeholder { color: transparent; } .form-floating > .form-control::placeholder { color: transparent; } .form-floating > .form-control:not(:-moz-placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:-webkit-autofill { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-select { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } .form-floating > .form-control:focus ~ label, .form-floating > .form-control:not(:placeholder-shown) ~ label, .form-floating > .form-select ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } .form-floating > .form-control:-webkit-autofill ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } .input-group { position: relative; display: flex; flex-wrap: wrap; align-items: stretch; width: 100%; } .input-group > .form-control, .input-group > .form-select { position: relative; flex: 1 1 auto; width: 1%; min-width: 0; } .input-group > .form-control:focus, .input-group > .form-select:focus { z-index: 3; } .input-group .btn { position: relative; z-index: 2; } .input-group .btn:focus { z-index: 3; } .input-group-text { display: flex; align-items: center; padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.25rem; } .input-group-lg > .form-control, .input-group-lg > .form-select, .input-group-lg > .input-group-text, .input-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.3rem; } .input-group-sm > .form-control, .input-group-sm > .form-select, .input-group-sm > .input-group-text, .input-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.2rem; } .input-group-lg > .form-select, .input-group-sm > .form-select { padding-right: 3rem; } .input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), .input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu), .input-group.has-validation > .dropdown-toggle:nth-last-child(n+4) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 0.875em; color: #198754; } .valid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: 0.1rem; font-size: 0.875rem; color: #fff; background-color: rgba(25, 135, 84, 0.9); border-radius: 0.25rem; } .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip, .is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip { display: block; } .was-validated .form-control:valid, .form-control.is-valid { border-color: #198754; padding-right: calc(1.5em + 0.75rem); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated textarea.form-control:valid, textarea.form-control.is-valid { padding-right: calc(1.5em + 0.75rem); background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .form-select:valid, .form-select.is-valid { border-color: #198754; } .was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { padding-right: 4.125rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-position: right 0.75rem center, center right 2.25rem; background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-select:valid:focus, .form-select.is-valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated .form-check-input:valid, .form-check-input.is-valid { border-color: #198754; } .was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { background-color: #198754; } .was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #198754; } .form-check-inline .form-check-input ~ .valid-feedback { margin-left: 0.5em; } .was-validated .input-group .form-control:valid, .input-group .form-control.is-valid, .was-validated .input-group .form-select:valid, .input-group .form-select.is-valid { z-index: 1; } .was-validated .input-group .form-control:valid:focus, .input-group .form-control.is-valid:focus, .was-validated .input-group .form-select:valid:focus, .input-group .form-select.is-valid:focus { z-index: 3; } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 0.875em; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: 0.1rem; font-size: 0.875rem; color: #fff; background-color: rgba(220, 53, 69, 0.9); border-radius: 0.25rem; } .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip, .is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; padding-right: calc(1.5em + 0.75rem); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { padding-right: calc(1.5em + 0.75rem); background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .form-select:invalid, .form-select.is-invalid { border-color: #dc3545; } .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { padding-right: 4.125rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-position: right 0.75rem center, center right 2.25rem; background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid, .form-check-input.is-invalid { border-color: #dc3545; } .was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { background-color: #dc3545; } .was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .form-check-inline .form-check-input ~ .invalid-feedback { margin-left: 0.5em; } .was-validated .input-group .form-control:invalid, .input-group .form-control.is-invalid, .was-validated .input-group .form-select:invalid, .input-group .form-select.is-invalid { z-index: 2; } .was-validated .input-group .form-control:invalid:focus, .input-group .form-control.is-invalid:focus, .was-validated .input-group .form-select:invalid:focus, .input-group .form-select.is-invalid:focus { z-index: 3; } .btn { display: inline-block; font-weight: 400; line-height: 1.5; color: #212529; text-align: center; text-decoration: none; vertical-align: middle; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { transition: none; } } .btn:hover { color: #212529; } .btn-check:focus + .btn, .btn:focus { outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .btn:disabled, .btn.disabled, fieldset:disabled .btn { pointer-events: none; opacity: 0.65; } .btn-primary { color: #fff; background-color: #0d6efd; border-color: #0d6efd; } .btn-primary:hover { color: #fff; background-color: #0b5ed7; border-color: #0a58ca; } .btn-check:focus + .btn-primary, .btn-primary:focus { color: #fff; background-color: #0b5ed7; border-color: #0a58ca; box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); } .btn-check:checked + .btn-primary, .btn-check:active + .btn-primary, .btn-primary:active, .btn-primary.active, .show > .btn-primary.dropdown-toggle { color: #fff; background-color: #0a58ca; border-color: #0a53be; } .btn-check:checked + .btn-primary:focus, .btn-check:active + .btn-primary:focus, .btn-primary:active:focus, .btn-primary.active:focus, .show > .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); } .btn-primary:disabled, .btn-primary.disabled { color: #fff; background-color: #0d6efd; border-color: #0d6efd; } .btn-secondary { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-secondary:hover { color: #fff; background-color: #5c636a; border-color: #565e64; } .btn-check:focus + .btn-secondary, .btn-secondary:focus { color: #fff; background-color: #5c636a; border-color: #565e64; box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); } .btn-check:checked + .btn-secondary, .btn-check:active + .btn-secondary, .btn-secondary:active, .btn-secondary.active, .show > .btn-secondary.dropdown-toggle { color: #fff; background-color: #565e64; border-color: #51585e; } .btn-check:checked + .btn-secondary:focus, .btn-check:active + .btn-secondary:focus, .btn-secondary:active:focus, .btn-secondary.active:focus, .show > .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); } .btn-secondary:disabled, .btn-secondary.disabled { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-success { color: #fff; background-color: #198754; border-color: #198754; } .btn-success:hover { color: #fff; background-color: #157347; border-color: #146c43; } .btn-check:focus + .btn-success, .btn-success:focus { color: #fff; background-color: #157347; border-color: #146c43; box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); } .btn-check:checked + .btn-success, .btn-check:active + .btn-success, .btn-success:active, .btn-success.active, .show > .btn-success.dropdown-toggle { color: #fff; background-color: #146c43; border-color: #13653f; } .btn-check:checked + .btn-success:focus, .btn-check:active + .btn-success:focus, .btn-success:active:focus, .btn-success.active:focus, .show > .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); } .btn-success:disabled, .btn-success.disabled { color: #fff; background-color: #198754; border-color: #198754; } .btn-info { color: #000; background-color: #0dcaf0; border-color: #0dcaf0; } .btn-info:hover { color: #000; background-color: #31d2f2; border-color: #25cff2; } .btn-check:focus + .btn-info, .btn-info:focus { color: #000; background-color: #31d2f2; border-color: #25cff2; box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); } .btn-check:checked + .btn-info, .btn-check:active + .btn-info, .btn-info:active, .btn-info.active, .show > .btn-info.dropdown-toggle { color: #000; background-color: #3dd5f3; border-color: #25cff2; } .btn-check:checked + .btn-info:focus, .btn-check:active + .btn-info:focus, .btn-info:active:focus, .btn-info.active:focus, .show > .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); } .btn-info:disabled, .btn-info.disabled { color: #000; background-color: #0dcaf0; border-color: #0dcaf0; } .btn-warning { color: #000; background-color: #ffc107; border-color: #ffc107; } .btn-warning:hover { color: #000; background-color: #ffca2c; border-color: #ffc720; } .btn-check:focus + .btn-warning, .btn-warning:focus { color: #000; background-color: #ffca2c; border-color: #ffc720; box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); } .btn-check:checked + .btn-warning, .btn-check:active + .btn-warning, .btn-warning:active, .btn-warning.active, .show > .btn-warning.dropdown-toggle { color: #000; background-color: #ffcd39; border-color: #ffc720; } .btn-check:checked + .btn-warning:focus, .btn-check:active + .btn-warning:focus, .btn-warning:active:focus, .btn-warning.active:focus, .show > .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); } .btn-warning:disabled, .btn-warning.disabled { color: #000; background-color: #ffc107; border-color: #ffc107; } .btn-danger { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-danger:hover { color: #fff; background-color: #bb2d3b; border-color: #b02a37; } .btn-check:focus + .btn-danger, .btn-danger:focus { color: #fff; background-color: #bb2d3b; border-color: #b02a37; box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); } .btn-check:checked + .btn-danger, .btn-check:active + .btn-danger, .btn-danger:active, .btn-danger.active, .show > .btn-danger.dropdown-toggle { color: #fff; background-color: #b02a37; border-color: #a52834; } .btn-check:checked + .btn-danger:focus, .btn-check:active + .btn-danger:focus, .btn-danger:active:focus, .btn-danger.active:focus, .show > .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); } .btn-danger:disabled, .btn-danger.disabled { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-light { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:hover { color: #000; background-color: #f9fafb; border-color: #f9fafb; } .btn-check:focus + .btn-light, .btn-light:focus { color: #000; background-color: #f9fafb; border-color: #f9fafb; box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); } .btn-check:checked + .btn-light, .btn-check:active + .btn-light, .btn-light:active, .btn-light.active, .show > .btn-light.dropdown-toggle { color: #000; background-color: #f9fafb; border-color: #f9fafb; } .btn-check:checked + .btn-light:focus, .btn-check:active + .btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show > .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); } .btn-light:disabled, .btn-light.disabled { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-dark { color: #fff; background-color: #212529; border-color: #212529; } .btn-dark:hover { color: #fff; background-color: #1c1f23; border-color: #1a1e21; } .btn-check:focus + .btn-dark, .btn-dark:focus { color: #fff; background-color: #1c1f23; border-color: #1a1e21; box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); } .btn-check:checked + .btn-dark, .btn-check:active + .btn-dark, .btn-dark:active, .btn-dark.active, .show > .btn-dark.dropdown-toggle { color: #fff; background-color: #1a1e21; border-color: #191c1f; } .btn-check:checked + .btn-dark:focus, .btn-check:active + .btn-dark:focus, .btn-dark:active:focus, .btn-dark.active:focus, .show > .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); } .btn-dark:disabled, .btn-dark.disabled { color: #fff; background-color: #212529; border-color: #212529; } .btn-outline-primary { color: #0d6efd; border-color: #0d6efd; } .btn-outline-primary:hover { color: #fff; background-color: #0d6efd; border-color: #0d6efd; } .btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus { box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); } .btn-check:checked + .btn-outline-primary, .btn-check:active + .btn-outline-primary, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary.dropdown-toggle.show { color: #fff; background-color: #0d6efd; border-color: #0d6efd; } .btn-check:checked + .btn-outline-primary:focus, .btn-check:active + .btn-outline-primary:focus, .btn-outline-primary:active:focus, .btn-outline-primary.active:focus, .btn-outline-primary.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); } .btn-outline-primary:disabled, .btn-outline-primary.disabled { color: #0d6efd; background-color: transparent; } .btn-outline-secondary { color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:hover { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus { box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); } .btn-check:checked + .btn-outline-secondary, .btn-check:active + .btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-check:checked + .btn-outline-secondary:focus, .btn-check:active + .btn-outline-secondary:focus, .btn-outline-secondary:active:focus, .btn-outline-secondary.active:focus, .btn-outline-secondary.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); } .btn-outline-secondary:disabled, .btn-outline-secondary.disabled { color: #6c757d; background-color: transparent; } .btn-outline-success { color: #198754; border-color: #198754; } .btn-outline-success:hover { color: #fff; background-color: #198754; border-color: #198754; } .btn-check:focus + .btn-outline-success, .btn-outline-success:focus { box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); } .btn-check:checked + .btn-outline-success, .btn-check:active + .btn-outline-success, .btn-outline-success:active, .btn-outline-success.active, .btn-outline-success.dropdown-toggle.show { color: #fff; background-color: #198754; border-color: #198754; } .btn-check:checked + .btn-outline-success:focus, .btn-check:active + .btn-outline-success:focus, .btn-outline-success:active:focus, .btn-outline-success.active:focus, .btn-outline-success.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); } .btn-outline-success:disabled, .btn-outline-success.disabled { color: #198754; background-color: transparent; } .btn-outline-info { color: #0dcaf0; border-color: #0dcaf0; } .btn-outline-info:hover { color: #000; background-color: #0dcaf0; border-color: #0dcaf0; } .btn-check:focus + .btn-outline-info, .btn-outline-info:focus { box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); } .btn-check:checked + .btn-outline-info, .btn-check:active + .btn-outline-info, .btn-outline-info:active, .btn-outline-info.active, .btn-outline-info.dropdown-toggle.show { color: #000; background-color: #0dcaf0; border-color: #0dcaf0; } .btn-check:checked + .btn-outline-info:focus, .btn-check:active + .btn-outline-info:focus, .btn-outline-info:active:focus, .btn-outline-info.active:focus, .btn-outline-info.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); } .btn-outline-info:disabled, .btn-outline-info.disabled { color: #0dcaf0; background-color: transparent; } .btn-outline-warning { color: #ffc107; border-color: #ffc107; } .btn-outline-warning:hover { color: #000; background-color: #ffc107; border-color: #ffc107; } .btn-check:focus + .btn-outline-warning, .btn-outline-warning:focus { box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); } .btn-check:checked + .btn-outline-warning, .btn-check:active + .btn-outline-warning, .btn-outline-warning:active, .btn-outline-warning.active, .btn-outline-warning.dropdown-toggle.show { color: #000; background-color: #ffc107; border-color: #ffc107; } .btn-check:checked + .btn-outline-warning:focus, .btn-check:active + .btn-outline-warning:focus, .btn-outline-warning:active:focus, .btn-outline-warning.active:focus, .btn-outline-warning.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); } .btn-outline-warning:disabled, .btn-outline-warning.disabled { color: #ffc107; background-color: transparent; } .btn-outline-danger { color: #dc3545; border-color: #dc3545; } .btn-outline-danger:hover { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-check:focus + .btn-outline-danger, .btn-outline-danger:focus { box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); } .btn-check:checked + .btn-outline-danger, .btn-check:active + .btn-outline-danger, .btn-outline-danger:active, .btn-outline-danger.active, .btn-outline-danger.dropdown-toggle.show { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-check:checked + .btn-outline-danger:focus, .btn-check:active + .btn-outline-danger:focus, .btn-outline-danger:active:focus, .btn-outline-danger.active:focus, .btn-outline-danger.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); } .btn-outline-danger:disabled, .btn-outline-danger.disabled { color: #dc3545; background-color: transparent; } .btn-outline-light { color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:hover { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-check:focus + .btn-outline-light, .btn-outline-light:focus { box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); } .btn-check:checked + .btn-outline-light, .btn-check:active + .btn-outline-light, .btn-outline-light:active, .btn-outline-light.active, .btn-outline-light.dropdown-toggle.show { color: #000; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-check:checked + .btn-outline-light:focus, .btn-check:active + .btn-outline-light:focus, .btn-outline-light:active:focus, .btn-outline-light.active:focus, .btn-outline-light.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); } .btn-outline-light:disabled, .btn-outline-light.disabled { color: #f8f9fa; background-color: transparent; } .btn-outline-dark { color: #212529; border-color: #212529; } .btn-outline-dark:hover { color: #fff; background-color: #212529; border-color: #212529; } .btn-check:focus + .btn-outline-dark, .btn-outline-dark:focus { box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); } .btn-check:checked + .btn-outline-dark, .btn-check:active + .btn-outline-dark, .btn-outline-dark:active, .btn-outline-dark.active, .btn-outline-dark.dropdown-toggle.show { color: #fff; background-color: #212529; border-color: #212529; } .btn-check:checked + .btn-outline-dark:focus, .btn-check:active + .btn-outline-dark:focus, .btn-outline-dark:active:focus, .btn-outline-dark.active:focus, .btn-outline-dark.dropdown-toggle.show:focus { box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); } .btn-outline-dark:disabled, .btn-outline-dark.disabled { color: #212529; background-color: transparent; } .btn-link { font-weight: 400; color: #0d6efd; text-decoration: underline; } .btn-link:hover { color: #0a58ca; } .btn-link:disabled, .btn-link.disabled { color: #6c757d; } .btn-lg, .btn-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.3rem; } .btn-sm, .btn-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.2rem; } .fade { transition: opacity 0.15s linear; } @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } .fade:not(.show) { opacity: 0; } .collapse:not(.show) { display: none; } .collapsing { height: 0; overflow: hidden; transition: height 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } } .dropup, .dropend, .dropdown, .dropstart { position: relative; } .dropdown-toggle { white-space: nowrap; } .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { position: absolute; z-index: 1000; display: none; min-width: 10rem; padding: 0.5rem 0; margin: 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; } .dropdown-menu[data-bs-popper] { top: 100%; left: 0; margin-top: 0.125rem; } .dropdown-menu-start { --bs-position: start; } .dropdown-menu-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-end { --bs-position: end; } .dropdown-menu-end[data-bs-popper] { right: 0; left: auto; } @media (min-width: 576px) { .dropdown-menu-sm-start { --bs-position: start; } .dropdown-menu-sm-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-sm-end { --bs-position: end; } .dropdown-menu-sm-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 768px) { .dropdown-menu-md-start { --bs-position: start; } .dropdown-menu-md-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-md-end { --bs-position: end; } .dropdown-menu-md-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 992px) { .dropdown-menu-lg-start { --bs-position: start; } .dropdown-menu-lg-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-lg-end { --bs-position: end; } .dropdown-menu-lg-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 1200px) { .dropdown-menu-xl-start { --bs-position: start; } .dropdown-menu-xl-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-xl-end { --bs-position: end; } .dropdown-menu-xl-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 1400px) { .dropdown-menu-xxl-start { --bs-position: start; } .dropdown-menu-xxl-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-xxl-end { --bs-position: end; } .dropdown-menu-xxl-end[data-bs-popper] { right: 0; left: auto; } } .dropup .dropdown-menu[data-bs-popper] { top: auto; bottom: 100%; margin-top: 0; margin-bottom: 0.125rem; } .dropup .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropend .dropdown-menu[data-bs-popper] { top: 0; right: auto; left: 100%; margin-top: 0; margin-left: 0.125rem; } .dropend .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } .dropend .dropdown-toggle:empty::after { margin-left: 0; } .dropend .dropdown-toggle::after { vertical-align: 0; } .dropstart .dropdown-menu[data-bs-popper] { top: 0; right: 100%; left: auto; margin-top: 0; margin-right: 0.125rem; } .dropstart .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; } .dropstart .dropdown-toggle::after { display: none; } .dropstart .dropdown-toggle::before { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropstart .dropdown-toggle:empty::after { margin-left: 0; } .dropstart .dropdown-toggle::before { vertical-align: 0; } .dropdown-divider { height: 0; margin: 0.5rem 0; overflow: hidden; border-top: 1px solid rgba(0, 0, 0, 0.15); } .dropdown-item { display: block; width: 100%; padding: 0.25rem 1rem; clear: both; font-weight: 400; color: #212529; text-align: inherit; text-decoration: none; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:hover, .dropdown-item:focus { color: #1e2125; background-color: #e9ecef; } .dropdown-item.active, .dropdown-item:active { color: #fff; text-decoration: none; background-color: #0d6efd; } .dropdown-item.disabled, .dropdown-item:disabled { color: #adb5bd; pointer-events: none; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: 0.5rem 1rem; margin-bottom: 0; font-size: 0.875rem; color: #6c757d; white-space: nowrap; } .dropdown-item-text { display: block; padding: 0.25rem 1rem; color: #212529; } .dropdown-menu-dark { color: #dee2e6; background-color: #343a40; border-color: rgba(0, 0, 0, 0.15); } .dropdown-menu-dark .dropdown-item { color: #dee2e6; } .dropdown-menu-dark .dropdown-item:hover, .dropdown-menu-dark .dropdown-item:focus { color: #fff; background-color: rgba(255, 255, 255, 0.15); } .dropdown-menu-dark .dropdown-item.active, .dropdown-menu-dark .dropdown-item:active { color: #fff; background-color: #0d6efd; } .dropdown-menu-dark .dropdown-item.disabled, .dropdown-menu-dark .dropdown-item:disabled { color: #adb5bd; } .dropdown-menu-dark .dropdown-divider { border-color: rgba(0, 0, 0, 0.15); } .dropdown-menu-dark .dropdown-item-text { color: #dee2e6; } .dropdown-menu-dark .dropdown-header { color: #adb5bd; } .btn-group, .btn-group-vertical { position: relative; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; flex: 1 1 auto; } .btn-group > .btn-check:checked + .btn, .btn-group > .btn-check:focus + .btn, .btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn-check:checked + .btn, .btn-group-vertical > .btn-check:focus + .btn, .btn-group-vertical > .btn:hover, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-toolbar { display: flex; flex-wrap: wrap; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) { margin-left: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:nth-child(n+3), .btn-group > :not(.btn-check) + .btn, .btn-group > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { margin-left: 0; } .dropstart .dropdown-toggle-split::before { margin-right: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group-vertical { flex-direction: column; align-items: flex-start; justify-content: center; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group { width: 100%; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn ~ .btn, .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-top-right-radius: 0; } .nav { display: flex; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: 0.5rem 1rem; color: #0d6efd; text-decoration: none; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .nav-link { transition: none; } } .nav-link:hover, .nav-link:focus { color: #0a58ca; } .nav-link.disabled { color: #6c757d; pointer-events: none; cursor: default; } .nav-tabs { border-bottom: 1px solid #dee2e6; } .nav-tabs .nav-link { margin-bottom: -1px; background: none; border: 1px solid transparent; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { border-color: #e9ecef #e9ecef #dee2e6; isolation: isolate; } .nav-tabs .nav-link.disabled { color: #6c757d; background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: #495057; background-color: #fff; border-color: #dee2e6 #dee2e6 #fff; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills .nav-link { background: none; border: 0; border-radius: 0.25rem; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; background-color: #0d6efd; } .nav-fill > .nav-link, .nav-fill .nav-item { flex: 1 1 auto; text-align: center; } .nav-justified > .nav-link, .nav-justified .nav-item { flex-basis: 0; flex-grow: 1; text-align: center; } .nav-fill .nav-item .nav-link, .nav-justified .nav-item .nav-link { width: 100%; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { position: relative; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar > .container, .navbar > .container-fluid, .navbar > .container-sm, .navbar > .container-md, .navbar > .container-lg, .navbar > .container-xl, .navbar > .container-xxl { display: flex; flex-wrap: inherit; align-items: center; justify-content: space-between; } .navbar-brand { padding-top: 0.3125rem; padding-bottom: 0.3125rem; margin-right: 1rem; font-size: 1.25rem; text-decoration: none; white-space: nowrap; } .navbar-nav { display: flex; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } .navbar-nav .dropdown-menu { position: static; } .navbar-text { padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar-collapse { flex-basis: 100%; flex-grow: 1; align-items: center; } .navbar-toggler { padding: 0.25rem 0.75rem; font-size: 1.25rem; line-height: 1; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; transition: box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .navbar-toggler { transition: none; } } .navbar-toggler:hover { text-decoration: none; } .navbar-toggler:focus { text-decoration: none; outline: 0; box-shadow: 0 0 0 0.25rem; } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; background-repeat: no-repeat; background-position: center; background-size: 100%; } .navbar-nav-scroll { max-height: var(--bs-scroll-height, 75vh); overflow-y: auto; } @media (min-width: 576px) { .navbar-expand-sm { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; } .navbar-expand-sm .navbar-nav-scroll { overflow: visible; } .navbar-expand-sm .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } } @media (min-width: 768px) { .navbar-expand-md { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-md .navbar-nav { flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; } .navbar-expand-md .navbar-nav-scroll { overflow: visible; } .navbar-expand-md .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } } @media (min-width: 992px) { .navbar-expand-lg { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; } .navbar-expand-lg .navbar-nav-scroll { overflow: visible; } .navbar-expand-lg .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } } @media (min-width: 1200px) { .navbar-expand-xl { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; } .navbar-expand-xl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xl .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } } @media (min-width: 1400px) { .navbar-expand-xxl { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-xxl .navbar-nav { flex-direction: row; } .navbar-expand-xxl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xxl .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; } .navbar-expand-xxl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xxl .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-xxl .navbar-toggler { display: none; } } .navbar-expand { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand .navbar-nav { flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .nav-link { padding-right: 0.5rem; padding-left: 0.5rem; } .navbar-expand .navbar-nav-scroll { overflow: visible; } .navbar-expand .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-light .navbar-brand { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.55); } .navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { color: rgba(0, 0, 0, 0.7); } .navbar-light .navbar-nav .nav-link.disabled { color: rgba(0, 0, 0, 0.3); } .navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .nav-link.active { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-toggler { color: rgba(0, 0, 0, 0.55); border-color: rgba(0, 0, 0, 0.1); } .navbar-light .navbar-toggler-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .navbar-light .navbar-text { color: rgba(0, 0, 0, 0.55); } .navbar-light .navbar-text a, .navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { color: rgba(0, 0, 0, 0.9); } .navbar-dark .navbar-brand { color: #fff; } .navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { color: #fff; } .navbar-dark .navbar-nav .nav-link { color: rgba(255, 255, 255, 0.55); } .navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-nav .nav-link.disabled { color: rgba(255, 255, 255, 0.25); } .navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .nav-link.active { color: #fff; } .navbar-dark .navbar-toggler { color: rgba(255, 255, 255, 0.55); border-color: rgba(255, 255, 255, 0.1); } .navbar-dark .navbar-toggler-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .navbar-dark .navbar-text { color: rgba(255, 255, 255, 0.55); } .navbar-dark .navbar-text a, .navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { color: #fff; } .card { position: relative; display: flex; flex-direction: column; min-width: 0; word-wrap: break-word; background-color: #fff; background-clip: border-box; border: 1px solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group { border-top: inherit; border-bottom: inherit; } .card > .list-group:first-child { border-top-width: 0; border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .card > .list-group:last-child { border-bottom-width: 0; border-bottom-right-radius: calc(0.25rem - 1px); border-bottom-left-radius: calc(0.25rem - 1px); } .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; } .card-body { flex: 1 1 auto; padding: 1rem 1rem; } .card-title { margin-bottom: 0.5rem; } .card-subtitle { margin-top: -0.25rem; margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link:hover { text-decoration: none; } .card-link + .card-link { margin-left: 1rem; } .card-header { padding: 0.5rem 1rem; margin-bottom: 0; background-color: rgba(0, 0, 0, 0.03); border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .card-header:first-child { border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; } .card-footer { padding: 0.5rem 1rem; background-color: rgba(0, 0, 0, 0.03); border-top: 1px solid rgba(0, 0, 0, 0.125); } .card-footer:last-child { border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); } .card-header-tabs { margin-right: -0.5rem; margin-bottom: -0.5rem; margin-left: -0.5rem; border-bottom: 0; } .card-header-pills { margin-right: -0.5rem; margin-left: -0.5rem; } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: 1rem; border-radius: calc(0.25rem - 1px); } .card-img, .card-img-top, .card-img-bottom { width: 100%; } .card-img, .card-img-top { border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .card-img, .card-img-bottom { border-bottom-right-radius: calc(0.25rem - 1px); border-bottom-left-radius: calc(0.25rem - 1px); } .card-group > .card { margin-bottom: 0.75rem; } @media (min-width: 576px) { .card-group { display: flex; flex-flow: row wrap; } .card-group > .card { flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-left: 0; border-left: 0; } .card-group > .card:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-top, .card-group > .card:not(:last-child) .card-header { border-top-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-bottom, .card-group > .card:not(:last-child) .card-footer { border-bottom-right-radius: 0; } .card-group > .card:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-top, .card-group > .card:not(:first-child) .card-header { border-top-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-bottom, .card-group > .card:not(:first-child) .card-footer { border-bottom-left-radius: 0; } } .accordion-button { position: relative; display: flex; align-items: center; width: 100%; padding: 1rem 1.25rem; font-size: 1rem; color: #212529; text-align: left; background-color: #fff; border: 0; border-radius: 0; overflow-anchor: none; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; } @media (prefers-reduced-motion: reduce) { .accordion-button { transition: none; } } .accordion-button:not(.collapsed) { color: #0c63e4; background-color: #e7f1ff; box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125); } .accordion-button:not(.collapsed)::after { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); transform: rotate(-180deg); } .accordion-button::after { flex-shrink: 0; width: 1.25rem; height: 1.25rem; margin-left: auto; content: ""; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-size: 1.25rem; transition: transform 0.2s ease-in-out; } @media (prefers-reduced-motion: reduce) { .accordion-button::after { transition: none; } } .accordion-button:hover { z-index: 2; } .accordion-button:focus { z-index: 3; border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .accordion-header { margin-bottom: 0; } .accordion-item { background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .accordion-item:first-of-type { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .accordion-item:first-of-type .accordion-button { border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .accordion-item:not(:first-of-type) { border-top: 0; } .accordion-item:last-of-type { border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .accordion-item:last-of-type .accordion-button.collapsed { border-bottom-right-radius: calc(0.25rem - 1px); border-bottom-left-radius: calc(0.25rem - 1px); } .accordion-item:last-of-type .accordion-collapse { border-bottom-right-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .accordion-body { padding: 1rem 1.25rem; } .accordion-flush .accordion-collapse { border-width: 0; } .accordion-flush .accordion-item { border-right: 0; border-left: 0; border-radius: 0; } .accordion-flush .accordion-item:first-child { border-top: 0; } .accordion-flush .accordion-item:last-child { border-bottom: 0; } .accordion-flush .accordion-item .accordion-button { border-radius: 0; } .breadcrumb { display: flex; flex-wrap: wrap; padding: 0 0; margin-bottom: 1rem; list-style: none; } .breadcrumb-item + .breadcrumb-item { padding-left: 0.5rem; } .breadcrumb-item + .breadcrumb-item::before { float: left; padding-right: 0.5rem; color: #6c757d; content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; } .breadcrumb-item.active { color: #6c757d; } .pagination { display: flex; padding-left: 0; list-style: none; } .page-link { position: relative; display: block; color: #0d6efd; text-decoration: none; background-color: #fff; border: 1px solid #dee2e6; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .page-link { transition: none; } } .page-link:hover { z-index: 2; color: #0a58ca; background-color: #e9ecef; border-color: #dee2e6; } .page-link:focus { z-index: 3; color: #0a58ca; background-color: #e9ecef; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .page-item:not(:first-child) .page-link { margin-left: -1px; } .page-item.active .page-link { z-index: 3; color: #fff; background-color: #0d6efd; border-color: #0d6efd; } .page-item.disabled .page-link { color: #6c757d; pointer-events: none; background-color: #fff; border-color: #dee2e6; } .page-link { padding: 0.375rem 0.75rem; } .page-item:first-child .page-link { border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } .pagination-lg .page-link { padding: 0.75rem 1.5rem; font-size: 1.25rem; } .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; font-size: 0.875rem; } .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.2rem; border-bottom-left-radius: 0.2rem; } .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.2rem; border-bottom-right-radius: 0.2rem; } .badge { display: inline-block; padding: 0.35em 0.65em; font-size: 0.75em; font-weight: 700; line-height: 1; color: #fff; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .alert { position: relative; padding: 1rem 1rem; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 0.25rem; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-right: 3rem; } .alert-dismissible .btn-close { position: absolute; top: 0; right: 0; z-index: 2; padding: 1.25rem 1rem; } .alert-primary { color: #084298; background-color: #cfe2ff; border-color: #b6d4fe; } .alert-primary .alert-link { color: #06357a; } .alert-secondary { color: #41464b; background-color: #e2e3e5; border-color: #d3d6d8; } .alert-secondary .alert-link { color: #34383c; } .alert-success { color: #0f5132; background-color: #d1e7dd; border-color: #badbcc; } .alert-success .alert-link { color: #0c4128; } .alert-info { color: #055160; background-color: #cff4fc; border-color: #b6effb; } .alert-info .alert-link { color: #04414d; } .alert-warning { color: #664d03; background-color: #fff3cd; border-color: #ffecb5; } .alert-warning .alert-link { color: #523e02; } .alert-danger { color: #842029; background-color: #f8d7da; border-color: #f5c2c7; } .alert-danger .alert-link { color: #6a1a21; } .alert-light { color: #636464; background-color: #fefefe; border-color: #fdfdfe; } .alert-light .alert-link { color: #4f5050; } .alert-dark { color: #141619; background-color: #d3d3d4; border-color: #bcbebf; } .alert-dark .alert-link { color: #101214; } @-webkit-keyframes progress-bar-stripes { 0% { background-position-x: 1rem; } } @keyframes progress-bar-stripes { 0% { background-position-x: 1rem; } } .progress { display: flex; height: 1rem; overflow: hidden; font-size: 0.75rem; background-color: #e9ecef; border-radius: 0.25rem; } .progress-bar { display: flex; flex-direction: column; justify-content: center; overflow: hidden; color: #fff; text-align: center; white-space: nowrap; background-color: #0d6efd; transition: width 0.6s ease; } @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: 1rem 1rem; } .progress-bar-animated { -webkit-animation: 1s linear infinite progress-bar-stripes; animation: 1s linear infinite progress-bar-stripes; } @media (prefers-reduced-motion: reduce) { .progress-bar-animated { -webkit-animation: none; animation: none; } } .list-group { display: flex; flex-direction: column; padding-left: 0; margin-bottom: 0; border-radius: 0.25rem; } .list-group-numbered { list-style-type: none; counter-reset: section; } .list-group-numbered > li::before { content: counters(section, ".") ". "; counter-increment: section; } .list-group-item-action { width: 100%; color: #495057; text-align: inherit; } .list-group-item-action:hover, .list-group-item-action:focus { z-index: 1; color: #495057; text-decoration: none; background-color: #f8f9fa; } .list-group-item-action:active { color: #212529; background-color: #e9ecef; } .list-group-item { position: relative; display: block; padding: 0.5rem 1rem; color: #212529; text-decoration: none; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .list-group-item:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; } .list-group-item:last-child { border-bottom-right-radius: inherit; border-bottom-left-radius: inherit; } .list-group-item.disabled, .list-group-item:disabled { color: #6c757d; pointer-events: none; background-color: #fff; } .list-group-item.active { z-index: 2; color: #fff; background-color: #0d6efd; border-color: #0d6efd; } .list-group-item + .list-group-item { border-top-width: 0; } .list-group-item + .list-group-item.active { margin-top: -1px; border-top-width: 1px; } .list-group-horizontal { flex-direction: row; } .list-group-horizontal > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal > .list-group-item.active { margin-top: 0; } .list-group-horizontal > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } @media (min-width: 576px) { .list-group-horizontal-sm { flex-direction: row; } .list-group-horizontal-sm > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-sm > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-sm > .list-group-item.active { margin-top: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 768px) { .list-group-horizontal-md { flex-direction: row; } .list-group-horizontal-md > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-md > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-md > .list-group-item.active { margin-top: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 992px) { .list-group-horizontal-lg { flex-direction: row; } .list-group-horizontal-lg > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-lg > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-lg > .list-group-item.active { margin-top: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 1200px) { .list-group-horizontal-xl { flex-direction: row; } .list-group-horizontal-xl > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-xl > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-xl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 1400px) { .list-group-horizontal-xxl { flex-direction: row; } .list-group-horizontal-xxl > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-xxl > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-xxl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xxl > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } .list-group-flush { border-radius: 0; } .list-group-flush > .list-group-item { border-width: 0 0 1px; } .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } .list-group-item-primary { color: #084298; background-color: #cfe2ff; } .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #084298; background-color: #bacbe6; } .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #084298; border-color: #084298; } .list-group-item-secondary { color: #41464b; background-color: #e2e3e5; } .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #41464b; background-color: #cbccce; } .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #41464b; border-color: #41464b; } .list-group-item-success { color: #0f5132; background-color: #d1e7dd; } .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { color: #0f5132; background-color: #bcd0c7; } .list-group-item-success.list-group-item-action.active { color: #fff; background-color: #0f5132; border-color: #0f5132; } .list-group-item-info { color: #055160; background-color: #cff4fc; } .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #055160; background-color: #badce3; } .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #055160; border-color: #055160; } .list-group-item-warning { color: #664d03; background-color: #fff3cd; } .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #664d03; background-color: #e6dbb9; } .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #664d03; border-color: #664d03; } .list-group-item-danger { color: #842029; background-color: #f8d7da; } .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { color: #842029; background-color: #dfc2c4; } .list-group-item-danger.list-group-item-action.active { color: #fff; background-color: #842029; border-color: #842029; } .list-group-item-light { color: #636464; background-color: #fefefe; } .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #636464; background-color: #e5e5e5; } .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #636464; border-color: #636464; } .list-group-item-dark { color: #141619; background-color: #d3d3d4; } .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { color: #141619; background-color: #bebebf; } .list-group-item-dark.list-group-item-action.active { color: #fff; background-color: #141619; border-color: #141619; } .btn-close { box-sizing: content-box; width: 1em; height: 1em; padding: 0.25em 0.25em; color: #000; background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; border: 0; border-radius: 0.25rem; opacity: 0.5; } .btn-close:hover { color: #000; text-decoration: none; opacity: 0.75; } .btn-close:focus { outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); opacity: 1; } .btn-close:disabled, .btn-close.disabled { pointer-events: none; -webkit-user-select: none; -moz-user-select: none; user-select: none; opacity: 0.25; } .btn-close-white { filter: invert(1) grayscale(100%) brightness(200%); } .toast { width: 350px; max-width: 100%; font-size: 0.875rem; pointer-events: auto; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); border-radius: 0.25rem; } .toast:not(.showing):not(.show) { opacity: 0; } .toast.hide { display: none; } .toast-container { width: -webkit-max-content; width: -moz-max-content; width: max-content; max-width: 100%; pointer-events: none; } .toast-container > :not(:last-child) { margin-bottom: 0.75rem; } .toast-header { display: flex; align-items: center; padding: 0.5rem 0.75rem; color: #6c757d; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .toast-header .btn-close { margin-right: -0.375rem; margin-left: 0.75rem; } .toast-body { padding: 0.75rem; word-wrap: break-word; } .modal { position: fixed; top: 0; left: 0; z-index: 1060; display: none; width: 100%; height: 100%; overflow-x: hidden; overflow-y: auto; outline: 0; } .modal-dialog { position: relative; width: auto; margin: 0.5rem; pointer-events: none; } .modal.fade .modal-dialog { transition: transform 0.3s ease-out; transform: translate(0, -50px); } @media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { transform: none; } .modal.modal-static .modal-dialog { transform: scale(1.02); } .modal-dialog-scrollable { height: calc(100% - 1rem); } .modal-dialog-scrollable .modal-content { max-height: 100%; overflow: hidden; } .modal-dialog-scrollable .modal-body { overflow-y: auto; } .modal-dialog-centered { display: flex; align-items: center; min-height: calc(100% - 1rem); } .modal-content { position: relative; display: flex; flex-direction: column; width: 100%; pointer-events: auto; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; outline: 0; } .modal-backdrop { position: fixed; top: 0; left: 0; z-index: 1040; width: 100vw; height: 100vh; background-color: #000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: 0.5; } .modal-header { display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; padding: 1rem 1rem; border-bottom: 1px solid #dee2e6; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .modal-header .btn-close { padding: 0.5rem 0.5rem; margin: -0.5rem -0.5rem -0.5rem auto; } .modal-title { margin-bottom: 0; line-height: 1.5; } .modal-body { position: relative; flex: 1 1 auto; padding: 1rem; } .modal-footer { display: flex; flex-wrap: wrap; flex-shrink: 0; align-items: center; justify-content: flex-end; padding: 0.75rem; border-top: 1px solid #dee2e6; border-bottom-right-radius: calc(0.3rem - 1px); border-bottom-left-radius: calc(0.3rem - 1px); } .modal-footer > * { margin: 0.25rem; } @media (min-width: 576px) { .modal-dialog { max-width: 500px; margin: 1.75rem auto; } .modal-dialog-scrollable { height: calc(100% - 3.5rem); } .modal-dialog-centered { min-height: calc(100% - 3.5rem); } .modal-sm { max-width: 300px; } } @media (min-width: 992px) { .modal-lg, .modal-xl { max-width: 800px; } } @media (min-width: 1200px) { .modal-xl { max-width: 1140px; } } .modal-fullscreen { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen .modal-header { border-radius: 0; } .modal-fullscreen .modal-body { overflow-y: auto; } .modal-fullscreen .modal-footer { border-radius: 0; } @media (max-width: 575.98px) { .modal-fullscreen-sm-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-sm-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-sm-down .modal-header { border-radius: 0; } .modal-fullscreen-sm-down .modal-body { overflow-y: auto; } .modal-fullscreen-sm-down .modal-footer { border-radius: 0; } } @media (max-width: 767.98px) { .modal-fullscreen-md-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-md-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-md-down .modal-header { border-radius: 0; } .modal-fullscreen-md-down .modal-body { overflow-y: auto; } .modal-fullscreen-md-down .modal-footer { border-radius: 0; } } @media (max-width: 991.98px) { .modal-fullscreen-lg-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-lg-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-lg-down .modal-header { border-radius: 0; } .modal-fullscreen-lg-down .modal-body { overflow-y: auto; } .modal-fullscreen-lg-down .modal-footer { border-radius: 0; } } @media (max-width: 1199.98px) { .modal-fullscreen-xl-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-xl-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-xl-down .modal-header { border-radius: 0; } .modal-fullscreen-xl-down .modal-body { overflow-y: auto; } .modal-fullscreen-xl-down .modal-footer { border-radius: 0; } } @media (max-width: 1399.98px) { .modal-fullscreen-xxl-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-xxl-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-xxl-down .modal-header { border-radius: 0; } .modal-fullscreen-xxl-down .modal-body { overflow-y: auto; } .modal-fullscreen-xxl-down .modal-footer { border-radius: 0; } } .tooltip { position: absolute; z-index: 1080; display: block; margin: 0; font-family: var(--bs-font-sans-serif); font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: 0.9; } .tooltip .tooltip-arrow { position: absolute; display: block; width: 0.8rem; height: 0.4rem; } .tooltip .tooltip-arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top, .bs-tooltip-auto[data-popper-placement^=top] { padding: 0.4rem 0; } .bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { bottom: 0; } .bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { top: -1px; border-width: 0.4rem 0.4rem 0; border-top-color: #000; } .bs-tooltip-end, .bs-tooltip-auto[data-popper-placement^=right] { padding: 0 0.4rem; } .bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { left: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { right: -1px; border-width: 0.4rem 0.4rem 0.4rem 0; border-right-color: #000; } .bs-tooltip-bottom, .bs-tooltip-auto[data-popper-placement^=bottom] { padding: 0.4rem 0; } .bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { top: 0; } .bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { bottom: -1px; border-width: 0 0.4rem 0.4rem; border-bottom-color: #000; } .bs-tooltip-start, .bs-tooltip-auto[data-popper-placement^=left] { padding: 0 0.4rem; } .bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { right: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { left: -1px; border-width: 0.4rem 0 0.4rem 0.4rem; border-left-color: #000; } .tooltip-inner { max-width: 200px; padding: 0.25rem 0.5rem; color: #fff; text-align: center; background-color: #000; border-radius: 0.25rem; } .popover { position: absolute; top: 0; left: 0 /* rtl:ignore */; z-index: 1070; display: block; max-width: 276px; font-family: var(--bs-font-sans-serif); font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; } .popover .popover-arrow { position: absolute; display: block; width: 1rem; height: 0.5rem; } .popover .popover-arrow::before, .popover .popover-arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; } .bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { bottom: calc(-0.5rem - 1px); } .bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { bottom: 0; border-width: 0.5rem 0.5rem 0; border-top-color: rgba(0, 0, 0, 0.25); } .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { bottom: 1px; border-width: 0.5rem 0.5rem 0; border-top-color: #fff; } .bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { left: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; } .bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { left: 0; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: rgba(0, 0, 0, 0.25); } .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { left: 1px; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: #fff; } .bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { top: calc(-0.5rem - 1px); } .bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { top: 0; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: rgba(0, 0, 0, 0.25); } .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { top: 1px; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: #fff; } .bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: 1rem; margin-left: -0.5rem; content: ""; border-bottom: 1px solid #f0f0f0; } .bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { right: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; } .bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { right: 0; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: rgba(0, 0, 0, 0.25); } .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { right: 1px; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: #fff; } .popover-header { padding: 0.5rem 1rem; margin-bottom: 0; font-size: 1rem; background-color: #f0f0f0; border-bottom: 1px solid rgba(0, 0, 0, 0.2); border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .popover-header:empty { display: none; } .popover-body { padding: 1rem 1rem; color: #212529; } .carousel { position: relative; } .carousel.pointer-event { touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: left; width: 100%; margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: transform 0.6s ease-in-out; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } /* rtl:begin:ignore */ .carousel-item-next:not(.carousel-item-start), .active.carousel-item-end { transform: translateX(100%); } .carousel-item-prev:not(.carousel-item-end), .active.carousel-item-start { transform: translateX(-100%); } /* rtl:end:ignore */ .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-start, .carousel-fade .carousel-item-prev.carousel-item-end { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { z-index: 0; opacity: 0; transition: opacity 0s 0.6s; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; z-index: 1; display: flex; align-items: center; justify-content: center; width: 15%; padding: 0; color: #fff; text-align: center; background: none; border: 0; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 2rem; height: 2rem; background-repeat: no-repeat; background-position: 50%; background-size: 100% 100%; } /* rtl:options: { "autoRename": true, "stringMap":[ { "name" : "prev-next", "search" : "prev", "replace" : "next" } ] } */ .carousel-control-prev-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); } .carousel-indicators { position: absolute; right: 0; bottom: 0; left: 0; z-index: 2; display: flex; justify-content: center; padding: 0; margin-right: 15%; margin-bottom: 1rem; margin-left: 15%; list-style: none; } .carousel-indicators [data-bs-target] { box-sizing: content-box; flex: 0 1 auto; width: 30px; height: 3px; padding: 0; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: 0.5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators [data-bs-target] { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; right: 15%; bottom: 1.25rem; left: 15%; padding-top: 1.25rem; padding-bottom: 1.25rem; color: #fff; text-align: center; } .carousel-dark .carousel-control-prev-icon, .carousel-dark .carousel-control-next-icon { filter: invert(1) grayscale(100); } .carousel-dark .carousel-indicators [data-bs-target] { background-color: #000; } .carousel-dark .carousel-caption { color: #000; } @-webkit-keyframes spinner-border { to { transform: rotate(360deg) /* rtl:ignore */; } } @keyframes spinner-border { to { transform: rotate(360deg) /* rtl:ignore */; } } .spinner-border { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; border: 0.25em solid currentColor; border-right-color: transparent; border-radius: 50%; -webkit-animation: 0.75s linear infinite spinner-border; animation: 0.75s linear infinite spinner-border; } .spinner-border-sm { width: 1rem; height: 1rem; border-width: 0.2em; } @-webkit-keyframes spinner-grow { 0% { transform: scale(0); } 50% { opacity: 1; transform: none; } } @keyframes spinner-grow { 0% { transform: scale(0); } 50% { opacity: 1; transform: none; } } .spinner-grow { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; background-color: currentColor; border-radius: 50%; opacity: 0; -webkit-animation: 0.75s linear infinite spinner-grow; animation: 0.75s linear infinite spinner-grow; } .spinner-grow-sm { width: 1rem; height: 1rem; } @media (prefers-reduced-motion: reduce) { .spinner-border, .spinner-grow { -webkit-animation-duration: 1.5s; animation-duration: 1.5s; } } .offcanvas { position: fixed; bottom: 0; z-index: 1050; display: flex; flex-direction: column; max-width: 100%; visibility: hidden; background-color: #fff; background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .offcanvas { transition: none; } } .offcanvas-header { display: flex; align-items: center; justify-content: space-between; padding: 1rem 1rem; } .offcanvas-header .btn-close { padding: 0.5rem 0.5rem; margin-top: -0.5rem; margin-right: -0.5rem; margin-bottom: -0.5rem; } .offcanvas-title { margin-bottom: 0; line-height: 1.5; } .offcanvas-body { flex-grow: 1; padding: 1rem 1rem; overflow-y: auto; } .offcanvas-start { top: 0; left: 0; width: 400px; border-right: 1px solid rgba(0, 0, 0, 0.2); transform: translateX(-100%); } .offcanvas-end { top: 0; right: 0; width: 400px; border-left: 1px solid rgba(0, 0, 0, 0.2); transform: translateX(100%); } .offcanvas-top { top: 0; right: 0; left: 0; height: 30vh; max-height: 100%; border-bottom: 1px solid rgba(0, 0, 0, 0.2); transform: translateY(-100%); } .offcanvas-bottom { right: 0; left: 0; height: 30vh; max-height: 100%; border-top: 1px solid rgba(0, 0, 0, 0.2); transform: translateY(100%); } .offcanvas.show { transform: none; } .clearfix::after { display: block; clear: both; content: ""; } .link-primary { color: #0d6efd; } .link-primary:hover, .link-primary:focus { color: #0a58ca; } .link-secondary { color: #6c757d; } .link-secondary:hover, .link-secondary:focus { color: #565e64; } .link-success { color: #198754; } .link-success:hover, .link-success:focus { color: #146c43; } .link-info { color: #0dcaf0; } .link-info:hover, .link-info:focus { color: #3dd5f3; } .link-warning { color: #ffc107; } .link-warning:hover, .link-warning:focus { color: #ffcd39; } .link-danger { color: #dc3545; } .link-danger:hover, .link-danger:focus { color: #b02a37; } .link-light { color: #f8f9fa; } .link-light:hover, .link-light:focus { color: #f9fafb; } .link-dark { color: #212529; } .link-dark:hover, .link-dark:focus { color: #1a1e21; } .ratio { position: relative; width: 100%; } .ratio::before { display: block; padding-top: var(--bs-aspect-ratio); content: ""; } .ratio > * { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .ratio-1x1 { --bs-aspect-ratio: 100%; } .ratio-4x3 { --bs-aspect-ratio: calc(3 / 4 * 100%); } .ratio-16x9 { --bs-aspect-ratio: calc(9 / 16 * 100%); } .ratio-21x9 { --bs-aspect-ratio: calc(9 / 21 * 100%); } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } @media (min-width: 576px) { .sticky-sm-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } @media (min-width: 768px) { .sticky-md-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } @media (min-width: 992px) { .sticky-lg-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } @media (min-width: 1200px) { .sticky-xl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } @media (min-width: 1400px) { .sticky-xxl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } .visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } .stretched-link::after { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1; content: ""; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .float-start { float: left !important; } .float-end { float: right !important; } .float-none { float: none !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .overflow-visible { overflow: visible !important; } .overflow-scroll { overflow: scroll !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .top-0 { top: 0 !important; } .top-50 { top: 50% !important; } .top-100 { top: 100% !important; } .bottom-0 { bottom: 0 !important; } .bottom-50 { bottom: 50% !important; } .bottom-100 { bottom: 100% !important; } .start-0 { left: 0 !important; } .start-50 { left: 50% !important; } .start-100 { left: 100% !important; } .end-0 { right: 0 !important; } .end-50 { right: 50% !important; } .end-100 { right: 100% !important; } .translate-middle { transform: translate(-50%, -50%) !important; } .translate-middle-x { transform: translateX(-50%) !important; } .translate-middle-y { transform: translateY(-50%) !important; } .border { border: 1px solid #dee2e6 !important; } .border-0 { border: 0 !important; } .border-top { border-top: 1px solid #dee2e6 !important; } .border-top-0 { border-top: 0 !important; } .border-end { border-right: 1px solid #dee2e6 !important; } .border-end-0 { border-right: 0 !important; } .border-bottom { border-bottom: 1px solid #dee2e6 !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-start { border-left: 1px solid #dee2e6 !important; } .border-start-0 { border-left: 0 !important; } .border-primary { border-color: #0d6efd !important; } .border-secondary { border-color: #6c757d !important; } .border-success { border-color: #198754 !important; } .border-info { border-color: #0dcaf0 !important; } .border-warning { border-color: #ffc107 !important; } .border-danger { border-color: #dc3545 !important; } .border-light { border-color: #f8f9fa !important; } .border-dark { border-color: #212529 !important; } .border-white { border-color: #fff !important; } .border-1 { border-width: 1px !important; } .border-2 { border-width: 2px !important; } .border-3 { border-width: 3px !important; } .border-4 { border-width: 4px !important; } .border-5 { border-width: 5px !important; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .mw-100 { max-width: 100% !important; } .vw-100 { width: 100vw !important; } .min-vw-100 { min-width: 100vw !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mh-100 { max-height: 100% !important; } .vh-100 { height: 100vh !important; } .min-vh-100 { min-height: 100vh !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .gap-0 { gap: 0 !important; } .gap-1 { gap: 0.25rem !important; } .gap-2 { gap: 0.5rem !important; } .gap-3 { gap: 1rem !important; } .gap-4 { gap: 1.5rem !important; } .gap-5 { gap: 3rem !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-auto { margin-right: auto !important; margin-left: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-right: 0 !important; } .me-1 { margin-right: 0.25rem !important; } .me-2 { margin-right: 0.5rem !important; } .me-3 { margin-right: 1rem !important; } .me-4 { margin-right: 1.5rem !important; } .me-5 { margin-right: 3rem !important; } .me-auto { margin-right: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-left: 0 !important; } .ms-1 { margin-left: 0.25rem !important; } .ms-2 { margin-left: 0.5rem !important; } .ms-3 { margin-left: 1rem !important; } .ms-4 { margin-left: 1.5rem !important; } .ms-5 { margin-left: 3rem !important; } .ms-auto { margin-left: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-right: 0 !important; } .pe-1 { padding-right: 0.25rem !important; } .pe-2 { padding-right: 0.5rem !important; } .pe-3 { padding-right: 1rem !important; } .pe-4 { padding-right: 1.5rem !important; } .pe-5 { padding-right: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-left: 0 !important; } .ps-1 { padding-left: 0.25rem !important; } .ps-2 { padding-left: 0.5rem !important; } .ps-3 { padding-left: 1rem !important; } .ps-4 { padding-left: 1.5rem !important; } .ps-5 { padding-left: 3rem !important; } .font-monospace { font-family: var(--bs-font-monospace) !important; } .fs-1 { font-size: calc(1.375rem + 1.5vw) !important; } .fs-2 { font-size: calc(1.325rem + 0.9vw) !important; } .fs-3 { font-size: calc(1.3rem + 0.6vw) !important; } .fs-4 { font-size: calc(1.275rem + 0.3vw) !important; } .fs-5 { font-size: 1.25rem !important; } .fs-6 { font-size: 1rem !important; } .fst-italic { font-style: italic !important; } .fst-normal { font-style: normal !important; } .fw-light { font-weight: 300 !important; } .fw-lighter { font-weight: lighter !important; } .fw-normal { font-weight: 400 !important; } .fw-bold { font-weight: 700 !important; } .fw-bolder { font-weight: bolder !important; } .lh-1 { line-height: 1 !important; } .lh-sm { line-height: 1.25 !important; } .lh-base { line-height: 1.5 !important; } .lh-lg { line-height: 2 !important; } .text-start { text-align: left !important; } .text-end { text-align: right !important; } .text-center { text-align: center !important; } .text-decoration-none { text-decoration: none !important; } .text-decoration-underline { text-decoration: underline !important; } .text-decoration-line-through { text-decoration: line-through !important; } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } /* rtl:begin:remove */ .text-break { word-wrap: break-word !important; word-break: break-word !important; } /* rtl:end:remove */ .text-primary { color: #0d6efd !important; } .text-secondary { color: #6c757d !important; } .text-success { color: #198754 !important; } .text-info { color: #0dcaf0 !important; } .text-warning { color: #ffc107 !important; } .text-danger { color: #dc3545 !important; } .text-light { color: #f8f9fa !important; } .text-dark { color: #212529 !important; } .text-white { color: #fff !important; } .text-body { color: #212529 !important; } .text-muted { color: #6c757d !important; } .text-black-50 { color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { color: rgba(255, 255, 255, 0.5) !important; } .text-reset { color: inherit !important; } .bg-primary { background-color: #0d6efd !important; } .bg-secondary { background-color: #6c757d !important; } .bg-success { background-color: #198754 !important; } .bg-info { background-color: #0dcaf0 !important; } .bg-warning { background-color: #ffc107 !important; } .bg-danger { background-color: #dc3545 !important; } .bg-light { background-color: #f8f9fa !important; } .bg-dark { background-color: #212529 !important; } .bg-body { background-color: #fff !important; } .bg-white { background-color: #fff !important; } .bg-transparent { background-color: transparent !important; } .bg-gradient { background-image: var(--bs-gradient) !important; } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; user-select: none !important; } .pe-none { pointer-events: none !important; } .pe-auto { pointer-events: auto !important; } .rounded { border-radius: 0.25rem !important; } .rounded-0 { border-radius: 0 !important; } .rounded-1 { border-radius: 0.2rem !important; } .rounded-2 { border-radius: 0.25rem !important; } .rounded-3 { border-radius: 0.3rem !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: 50rem !important; } .rounded-top { border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; } .rounded-end { border-top-right-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; } .rounded-bottom { border-bottom-right-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-start { border-bottom-left-radius: 0.25rem !important; border-top-left-radius: 0.25rem !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media (min-width: 576px) { .float-sm-start { float: left !important; } .float-sm-end { float: right !important; } .float-sm-none { float: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .gap-sm-0 { gap: 0 !important; } .gap-sm-1 { gap: 0.25rem !important; } .gap-sm-2 { gap: 0.5rem !important; } .gap-sm-3 { gap: 1rem !important; } .gap-sm-4 { gap: 1.5rem !important; } .gap-sm-5 { gap: 3rem !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-sm-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-sm-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-sm-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-sm-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-sm-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-sm-auto { margin-right: auto !important; margin-left: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-right: 0 !important; } .me-sm-1 { margin-right: 0.25rem !important; } .me-sm-2 { margin-right: 0.5rem !important; } .me-sm-3 { margin-right: 1rem !important; } .me-sm-4 { margin-right: 1.5rem !important; } .me-sm-5 { margin-right: 3rem !important; } .me-sm-auto { margin-right: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-left: 0 !important; } .ms-sm-1 { margin-left: 0.25rem !important; } .ms-sm-2 { margin-left: 0.5rem !important; } .ms-sm-3 { margin-left: 1rem !important; } .ms-sm-4 { margin-left: 1.5rem !important; } .ms-sm-5 { margin-left: 3rem !important; } .ms-sm-auto { margin-left: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-sm-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-sm-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-sm-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-sm-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-sm-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-right: 0 !important; } .pe-sm-1 { padding-right: 0.25rem !important; } .pe-sm-2 { padding-right: 0.5rem !important; } .pe-sm-3 { padding-right: 1rem !important; } .pe-sm-4 { padding-right: 1.5rem !important; } .pe-sm-5 { padding-right: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-left: 0 !important; } .ps-sm-1 { padding-left: 0.25rem !important; } .ps-sm-2 { padding-left: 0.5rem !important; } .ps-sm-3 { padding-left: 1rem !important; } .ps-sm-4 { padding-left: 1.5rem !important; } .ps-sm-5 { padding-left: 3rem !important; } .text-sm-start { text-align: left !important; } .text-sm-end { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .float-md-start { float: left !important; } .float-md-end { float: right !important; } .float-md-none { float: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .gap-md-0 { gap: 0 !important; } .gap-md-1 { gap: 0.25rem !important; } .gap-md-2 { gap: 0.5rem !important; } .gap-md-3 { gap: 1rem !important; } .gap-md-4 { gap: 1.5rem !important; } .gap-md-5 { gap: 3rem !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-md-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-md-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-md-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-md-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-md-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-md-auto { margin-right: auto !important; margin-left: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-right: 0 !important; } .me-md-1 { margin-right: 0.25rem !important; } .me-md-2 { margin-right: 0.5rem !important; } .me-md-3 { margin-right: 1rem !important; } .me-md-4 { margin-right: 1.5rem !important; } .me-md-5 { margin-right: 3rem !important; } .me-md-auto { margin-right: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-left: 0 !important; } .ms-md-1 { margin-left: 0.25rem !important; } .ms-md-2 { margin-left: 0.5rem !important; } .ms-md-3 { margin-left: 1rem !important; } .ms-md-4 { margin-left: 1.5rem !important; } .ms-md-5 { margin-left: 3rem !important; } .ms-md-auto { margin-left: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-md-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-md-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-md-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-md-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-md-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-right: 0 !important; } .pe-md-1 { padding-right: 0.25rem !important; } .pe-md-2 { padding-right: 0.5rem !important; } .pe-md-3 { padding-right: 1rem !important; } .pe-md-4 { padding-right: 1.5rem !important; } .pe-md-5 { padding-right: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-left: 0 !important; } .ps-md-1 { padding-left: 0.25rem !important; } .ps-md-2 { padding-left: 0.5rem !important; } .ps-md-3 { padding-left: 1rem !important; } .ps-md-4 { padding-left: 1.5rem !important; } .ps-md-5 { padding-left: 3rem !important; } .text-md-start { text-align: left !important; } .text-md-end { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .float-lg-start { float: left !important; } .float-lg-end { float: right !important; } .float-lg-none { float: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .gap-lg-0 { gap: 0 !important; } .gap-lg-1 { gap: 0.25rem !important; } .gap-lg-2 { gap: 0.5rem !important; } .gap-lg-3 { gap: 1rem !important; } .gap-lg-4 { gap: 1.5rem !important; } .gap-lg-5 { gap: 3rem !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-lg-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-lg-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-lg-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-lg-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-lg-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-lg-auto { margin-right: auto !important; margin-left: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-right: 0 !important; } .me-lg-1 { margin-right: 0.25rem !important; } .me-lg-2 { margin-right: 0.5rem !important; } .me-lg-3 { margin-right: 1rem !important; } .me-lg-4 { margin-right: 1.5rem !important; } .me-lg-5 { margin-right: 3rem !important; } .me-lg-auto { margin-right: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-left: 0 !important; } .ms-lg-1 { margin-left: 0.25rem !important; } .ms-lg-2 { margin-left: 0.5rem !important; } .ms-lg-3 { margin-left: 1rem !important; } .ms-lg-4 { margin-left: 1.5rem !important; } .ms-lg-5 { margin-left: 3rem !important; } .ms-lg-auto { margin-left: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-lg-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-lg-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-lg-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-lg-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-lg-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-right: 0 !important; } .pe-lg-1 { padding-right: 0.25rem !important; } .pe-lg-2 { padding-right: 0.5rem !important; } .pe-lg-3 { padding-right: 1rem !important; } .pe-lg-4 { padding-right: 1.5rem !important; } .pe-lg-5 { padding-right: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-left: 0 !important; } .ps-lg-1 { padding-left: 0.25rem !important; } .ps-lg-2 { padding-left: 0.5rem !important; } .ps-lg-3 { padding-left: 1rem !important; } .ps-lg-4 { padding-left: 1.5rem !important; } .ps-lg-5 { padding-left: 3rem !important; } .text-lg-start { text-align: left !important; } .text-lg-end { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .float-xl-start { float: left !important; } .float-xl-end { float: right !important; } .float-xl-none { float: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .gap-xl-0 { gap: 0 !important; } .gap-xl-1 { gap: 0.25rem !important; } .gap-xl-2 { gap: 0.5rem !important; } .gap-xl-3 { gap: 1rem !important; } .gap-xl-4 { gap: 1.5rem !important; } .gap-xl-5 { gap: 3rem !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-right: 0 !important; } .me-xl-1 { margin-right: 0.25rem !important; } .me-xl-2 { margin-right: 0.5rem !important; } .me-xl-3 { margin-right: 1rem !important; } .me-xl-4 { margin-right: 1.5rem !important; } .me-xl-5 { margin-right: 3rem !important; } .me-xl-auto { margin-right: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-left: 0 !important; } .ms-xl-1 { margin-left: 0.25rem !important; } .ms-xl-2 { margin-left: 0.5rem !important; } .ms-xl-3 { margin-left: 1rem !important; } .ms-xl-4 { margin-left: 1.5rem !important; } .ms-xl-5 { margin-left: 3rem !important; } .ms-xl-auto { margin-left: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-right: 0 !important; } .pe-xl-1 { padding-right: 0.25rem !important; } .pe-xl-2 { padding-right: 0.5rem !important; } .pe-xl-3 { padding-right: 1rem !important; } .pe-xl-4 { padding-right: 1.5rem !important; } .pe-xl-5 { padding-right: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-left: 0 !important; } .ps-xl-1 { padding-left: 0.25rem !important; } .ps-xl-2 { padding-left: 0.5rem !important; } .ps-xl-3 { padding-left: 1rem !important; } .ps-xl-4 { padding-left: 1.5rem !important; } .ps-xl-5 { padding-left: 3rem !important; } .text-xl-start { text-align: left !important; } .text-xl-end { text-align: right !important; } .text-xl-center { text-align: center !important; } } @media (min-width: 1400px) { .float-xxl-start { float: left !important; } .float-xxl-end { float: right !important; } .float-xxl-none { float: none !important; } .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .gap-xxl-0 { gap: 0 !important; } .gap-xxl-1 { gap: 0.25rem !important; } .gap-xxl-2 { gap: 0.5rem !important; } .gap-xxl-3 { gap: 1rem !important; } .gap-xxl-4 { gap: 1.5rem !important; } .gap-xxl-5 { gap: 3rem !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xxl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xxl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xxl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xxl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xxl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xxl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-right: 0 !important; } .me-xxl-1 { margin-right: 0.25rem !important; } .me-xxl-2 { margin-right: 0.5rem !important; } .me-xxl-3 { margin-right: 1rem !important; } .me-xxl-4 { margin-right: 1.5rem !important; } .me-xxl-5 { margin-right: 3rem !important; } .me-xxl-auto { margin-right: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-left: 0 !important; } .ms-xxl-1 { margin-left: 0.25rem !important; } .ms-xxl-2 { margin-left: 0.5rem !important; } .ms-xxl-3 { margin-left: 1rem !important; } .ms-xxl-4 { margin-left: 1.5rem !important; } .ms-xxl-5 { margin-left: 3rem !important; } .ms-xxl-auto { margin-left: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xxl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xxl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xxl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xxl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xxl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-right: 0 !important; } .pe-xxl-1 { padding-right: 0.25rem !important; } .pe-xxl-2 { padding-right: 0.5rem !important; } .pe-xxl-3 { padding-right: 1rem !important; } .pe-xxl-4 { padding-right: 1.5rem !important; } .pe-xxl-5 { padding-right: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-left: 0 !important; } .ps-xxl-1 { padding-left: 0.25rem !important; } .ps-xxl-2 { padding-left: 0.5rem !important; } .ps-xxl-3 { padding-left: 1rem !important; } .ps-xxl-4 { padding-left: 1.5rem !important; } .ps-xxl-5 { padding-left: 3rem !important; } .text-xxl-start { text-align: left !important; } .text-xxl-end { text-align: right !important; } .text-xxl-center { text-align: center !important; } } @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; } .fs-2 { font-size: 2rem !important; } .fs-3 { font-size: 1.75rem !important; } .fs-4 { font-size: 1.5rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: public/css/fatrat.css ================================================ .frc-option-add-edit table p { color: #838383; font-size: 12px; } .spider-tab-content table p { color: #838383; font-size: 12px; } .spider-tab-content p { color: #838383; font-size: 12px; } .todo-and-author-class li { color: #336600; font-size: 13px; } .frc-appreciate-class li { float: left; font-size: 12px; width: 150px; color: #0027ff; } .p-tips-style { color: #9e9d24; font-size: 12px; padding-top: 5px; } .p-tips-style-color1 { color: #3300aa; font-size: 12px; padding-top: 5px; } .fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear};fa-spin{0%{-webkit-transform:rotate(0deg); transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg); transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}} ul { padding-left: 0; } ================================================ FILE: public/js/bootstrap.js ================================================ /*! * Bootstrap v5.0.2 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core')) : typeof define === 'function' && define.amd ? define(['@popperjs/core'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory(global.Popper)); }(this, (function (Popper) { 'use strict'; function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n['default'] = e; return Object.freeze(n); } var Popper__namespace = /*#__PURE__*/_interopNamespace(Popper); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): dom/selector-engine.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NODE_TEXT = 3; const SelectorEngine = { find(selector, element = document.documentElement) { return [].concat(...Element.prototype.querySelectorAll.call(element, selector)); }, findOne(selector, element = document.documentElement) { return Element.prototype.querySelector.call(element, selector); }, children(element, selector) { return [].concat(...element.children).filter(child => child.matches(selector)); }, parents(element, selector) { const parents = []; let ancestor = element.parentNode; while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== NODE_TEXT) { if (ancestor.matches(selector)) { parents.push(ancestor); } ancestor = ancestor.parentNode; } return parents; }, prev(element, selector) { let previous = element.previousElementSibling; while (previous) { if (previous.matches(selector)) { return [previous]; } previous = previous.previousElementSibling; } return []; }, next(element, selector) { let next = element.nextElementSibling; while (next) { if (next.matches(selector)) { return [next]; } next = next.nextElementSibling; } return []; } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): util/index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const MAX_UID = 1000000; const MILLISECONDS_MULTIPLIER = 1000; const TRANSITION_END = 'transitionend'; // Shoutout AngusCroll (https://goo.gl/pxwQGp) const toType = obj => { if (obj === null || obj === undefined) { return `${obj}`; } return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); }; /** * -------------------------------------------------------------------------- * Public Util Api * -------------------------------------------------------------------------- */ const getUID = prefix => { do { prefix += Math.floor(Math.random() * MAX_UID); } while (document.getElementById(prefix)); return prefix; }; const getSelector = element => { let selector = element.getAttribute('data-bs-target'); if (!selector || selector === '#') { let hrefAttr = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, // so everything starting with `#` or `.`. If a "real" URL is used as the selector, // `document.querySelector` will rightfully complain it is invalid. // See https://github.com/twbs/bootstrap/issues/32273 if (!hrefAttr || !hrefAttr.includes('#') && !hrefAttr.startsWith('.')) { return null; } // Just in case some CMS puts out a full URL with the anchor appended if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) { hrefAttr = `#${hrefAttr.split('#')[1]}`; } selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null; } return selector; }; const getSelectorFromElement = element => { const selector = getSelector(element); if (selector) { return document.querySelector(selector) ? selector : null; } return null; }; const getElementFromSelector = element => { const selector = getSelector(element); return selector ? document.querySelector(selector) : null; }; const getTransitionDurationFromElement = element => { if (!element) { return 0; } // Get transition-duration of the element let { transitionDuration, transitionDelay } = window.getComputedStyle(element); const floatTransitionDuration = Number.parseFloat(transitionDuration); const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found if (!floatTransitionDuration && !floatTransitionDelay) { return 0; } // If multiple durations are defined, take the first transitionDuration = transitionDuration.split(',')[0]; transitionDelay = transitionDelay.split(',')[0]; return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; }; const triggerTransitionEnd = element => { element.dispatchEvent(new Event(TRANSITION_END)); }; const isElement = obj => { if (!obj || typeof obj !== 'object') { return false; } if (typeof obj.jquery !== 'undefined') { obj = obj[0]; } return typeof obj.nodeType !== 'undefined'; }; const getElement = obj => { if (isElement(obj)) { // it's a jQuery object or a node element return obj.jquery ? obj[0] : obj; } if (typeof obj === 'string' && obj.length > 0) { return SelectorEngine.findOne(obj); } return null; }; const typeCheckConfig = (componentName, config, configTypes) => { Object.keys(configTypes).forEach(property => { const expectedTypes = configTypes[property]; const value = config[property]; const valueType = value && isElement(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new TypeError(`${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); } }); }; const isVisible = element => { if (!isElement(element) || element.getClientRects().length === 0) { return false; } return getComputedStyle(element).getPropertyValue('visibility') === 'visible'; }; const isDisabled = element => { if (!element || element.nodeType !== Node.ELEMENT_NODE) { return true; } if (element.classList.contains('disabled')) { return true; } if (typeof element.disabled !== 'undefined') { return element.disabled; } return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; }; const findShadowRoot = element => { if (!document.documentElement.attachShadow) { return null; } // Can find the shadow root otherwise it'll return the document if (typeof element.getRootNode === 'function') { const root = element.getRootNode(); return root instanceof ShadowRoot ? root : null; } if (element instanceof ShadowRoot) { return element; } // when we don't find a shadow root if (!element.parentNode) { return null; } return findShadowRoot(element.parentNode); }; const noop = () => {}; const reflow = element => element.offsetHeight; const getjQuery = () => { const { jQuery } = window; if (jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { return jQuery; } return null; }; const DOMContentLoadedCallbacks = []; const onDOMContentLoaded = callback => { if (document.readyState === 'loading') { // add listener on the first call when the document is in loading state if (!DOMContentLoadedCallbacks.length) { document.addEventListener('DOMContentLoaded', () => { DOMContentLoadedCallbacks.forEach(callback => callback()); }); } DOMContentLoadedCallbacks.push(callback); } else { callback(); } }; const isRTL = () => document.documentElement.dir === 'rtl'; const defineJQueryPlugin = plugin => { onDOMContentLoaded(() => { const $ = getjQuery(); /* istanbul ignore if */ if ($) { const name = plugin.NAME; const JQUERY_NO_CONFLICT = $.fn[name]; $.fn[name] = plugin.jQueryInterface; $.fn[name].Constructor = plugin; $.fn[name].noConflict = () => { $.fn[name] = JQUERY_NO_CONFLICT; return plugin.jQueryInterface; }; } }); }; const execute = callback => { if (typeof callback === 'function') { callback(); } }; const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { if (!waitForTransition) { execute(callback); return; } const durationPadding = 5; const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; let called = false; const handler = ({ target }) => { if (target !== transitionElement) { return; } called = true; transitionElement.removeEventListener(TRANSITION_END, handler); execute(callback); }; transitionElement.addEventListener(TRANSITION_END, handler); setTimeout(() => { if (!called) { triggerTransitionEnd(transitionElement); } }, emulatedDuration); }; /** * Return the previous/next element of a list. * * @param {array} list The list of elements * @param activeElement The active element * @param shouldGetNext Choose to get next or previous element * @param isCycleAllowed * @return {Element|elem} The proper element */ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { let index = list.indexOf(activeElement); // if the element does not exist in the list return an element depending on the direction and if cycle is allowed if (index === -1) { return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0]; } const listLength = list.length; index += shouldGetNext ? 1 : -1; if (isCycleAllowed) { index = (index + listLength) % listLength; } return list[Math.max(0, Math.min(index, listLength - 1))]; }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): dom/event-handler.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const namespaceRegex = /[^.]*(?=\..*)\.|.*/; const stripNameRegex = /\..*/; const stripUidRegex = /::\d+$/; const eventRegistry = {}; // Events storage let uidEvent = 1; const customEvents = { mouseenter: 'mouseover', mouseleave: 'mouseout' }; const customEventsRegex = /^(mouseenter|mouseleave)/i; const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']); /** * ------------------------------------------------------------------------ * Private methods * ------------------------------------------------------------------------ */ function getUidEvent(element, uid) { return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; } function getEvent(element) { const uid = getUidEvent(element); element.uidEvent = uid; eventRegistry[uid] = eventRegistry[uid] || {}; return eventRegistry[uid]; } function bootstrapHandler(element, fn) { return function handler(event) { event.delegateTarget = element; if (handler.oneOff) { EventHandler.off(element, event.type, fn); } return fn.apply(element, [event]); }; } function bootstrapDelegationHandler(element, selector, fn) { return function handler(event) { const domElements = element.querySelectorAll(selector); for (let { target } = event; target && target !== this; target = target.parentNode) { for (let i = domElements.length; i--;) { if (domElements[i] === target) { event.delegateTarget = target; if (handler.oneOff) { // eslint-disable-next-line unicorn/consistent-destructuring EventHandler.off(element, event.type, selector, fn); } return fn.apply(target, [event]); } } } // To please ESLint return null; }; } function findHandler(events, handler, delegationSelector = null) { const uidEventList = Object.keys(events); for (let i = 0, len = uidEventList.length; i < len; i++) { const event = events[uidEventList[i]]; if (event.originalHandler === handler && event.delegationSelector === delegationSelector) { return event; } } return null; } function normalizeParams(originalTypeEvent, handler, delegationFn) { const delegation = typeof handler === 'string'; const originalHandler = delegation ? delegationFn : handler; let typeEvent = getTypeEvent(originalTypeEvent); const isNative = nativeEvents.has(typeEvent); if (!isNative) { typeEvent = originalTypeEvent; } return [delegation, originalHandler, typeEvent]; } function addHandler(element, originalTypeEvent, handler, delegationFn, oneOff) { if (typeof originalTypeEvent !== 'string' || !element) { return; } if (!handler) { handler = delegationFn; delegationFn = null; } // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position // this prevents the handler from being dispatched the same way as mouseover or mouseout does if (customEventsRegex.test(originalTypeEvent)) { const wrapFn = fn => { return function (event) { if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) { return fn.call(this, event); } }; }; if (delegationFn) { delegationFn = wrapFn(delegationFn); } else { handler = wrapFn(handler); } } const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn); const events = getEvent(element); const handlers = events[typeEvent] || (events[typeEvent] = {}); const previousFn = findHandler(handlers, originalHandler, delegation ? handler : null); if (previousFn) { previousFn.oneOff = previousFn.oneOff && oneOff; return; } const uid = getUidEvent(originalHandler, originalTypeEvent.replace(namespaceRegex, '')); const fn = delegation ? bootstrapDelegationHandler(element, handler, delegationFn) : bootstrapHandler(element, handler); fn.delegationSelector = delegation ? handler : null; fn.originalHandler = originalHandler; fn.oneOff = oneOff; fn.uidEvent = uid; handlers[uid] = fn; element.addEventListener(typeEvent, fn, delegation); } function removeHandler(element, events, typeEvent, handler, delegationSelector) { const fn = findHandler(events[typeEvent], handler, delegationSelector); if (!fn) { return; } element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)); delete events[typeEvent][fn.uidEvent]; } function removeNamespacedHandlers(element, events, typeEvent, namespace) { const storeElementEvent = events[typeEvent] || {}; Object.keys(storeElementEvent).forEach(handlerKey => { if (handlerKey.includes(namespace)) { const event = storeElementEvent[handlerKey]; removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector); } }); } function getTypeEvent(event) { // allow to get the native events from namespaced events ('click.bs.button' --> 'click') event = event.replace(stripNameRegex, ''); return customEvents[event] || event; } const EventHandler = { on(element, event, handler, delegationFn) { addHandler(element, event, handler, delegationFn, false); }, one(element, event, handler, delegationFn) { addHandler(element, event, handler, delegationFn, true); }, off(element, originalTypeEvent, handler, delegationFn) { if (typeof originalTypeEvent !== 'string' || !element) { return; } const [delegation, originalHandler, typeEvent] = normalizeParams(originalTypeEvent, handler, delegationFn); const inNamespace = typeEvent !== originalTypeEvent; const events = getEvent(element); const isNamespace = originalTypeEvent.startsWith('.'); if (typeof originalHandler !== 'undefined') { // Simplest case: handler is passed, remove that listener ONLY. if (!events || !events[typeEvent]) { return; } removeHandler(element, events, typeEvent, originalHandler, delegation ? handler : null); return; } if (isNamespace) { Object.keys(events).forEach(elementEvent => { removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); }); } const storeElementEvent = events[typeEvent] || {}; Object.keys(storeElementEvent).forEach(keyHandlers => { const handlerKey = keyHandlers.replace(stripUidRegex, ''); if (!inNamespace || originalTypeEvent.includes(handlerKey)) { const event = storeElementEvent[keyHandlers]; removeHandler(element, events, typeEvent, event.originalHandler, event.delegationSelector); } }); }, trigger(element, event, args) { if (typeof event !== 'string' || !element) { return null; } const $ = getjQuery(); const typeEvent = getTypeEvent(event); const inNamespace = event !== typeEvent; const isNative = nativeEvents.has(typeEvent); let jQueryEvent; let bubbles = true; let nativeDispatch = true; let defaultPrevented = false; let evt = null; if (inNamespace && $) { jQueryEvent = $.Event(event, args); $(element).trigger(jQueryEvent); bubbles = !jQueryEvent.isPropagationStopped(); nativeDispatch = !jQueryEvent.isImmediatePropagationStopped(); defaultPrevented = jQueryEvent.isDefaultPrevented(); } if (isNative) { evt = document.createEvent('HTMLEvents'); evt.initEvent(typeEvent, bubbles, true); } else { evt = new CustomEvent(event, { bubbles, cancelable: true }); } // merge custom information in our event if (typeof args !== 'undefined') { Object.keys(args).forEach(key => { Object.defineProperty(evt, key, { get() { return args[key]; } }); }); } if (defaultPrevented) { evt.preventDefault(); } if (nativeDispatch) { element.dispatchEvent(evt); } if (evt.defaultPrevented && typeof jQueryEvent !== 'undefined') { jQueryEvent.preventDefault(); } return evt; } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): dom/data.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const elementMap = new Map(); var Data = { set(element, key, instance) { if (!elementMap.has(element)) { elementMap.set(element, new Map()); } const instanceMap = elementMap.get(element); // make it clear we only want one instance per element // can be removed later when multiple key/instances are fine to be used if (!instanceMap.has(key) && instanceMap.size !== 0) { // eslint-disable-next-line no-console console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`); return; } instanceMap.set(key, instance); }, get(element, key) { if (elementMap.has(element)) { return elementMap.get(element).get(key) || null; } return null; }, remove(element, key) { if (!elementMap.has(element)) { return; } const instanceMap = elementMap.get(element); instanceMap.delete(key); // free up element references if there are no instances left for an element if (instanceMap.size === 0) { elementMap.delete(element); } } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): base-component.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const VERSION = '5.0.2'; class BaseComponent { constructor(element) { element = getElement(element); if (!element) { return; } this._element = element; Data.set(this._element, this.constructor.DATA_KEY, this); } dispose() { Data.remove(this._element, this.constructor.DATA_KEY); EventHandler.off(this._element, this.constructor.EVENT_KEY); Object.getOwnPropertyNames(this).forEach(propertyName => { this[propertyName] = null; }); } _queueCallback(callback, element, isAnimated = true) { executeAfterTransition(callback, element, isAnimated); } /** Static */ static getInstance(element) { return Data.get(element, this.DATA_KEY); } static getOrCreateInstance(element, config = {}) { return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null); } static get VERSION() { return VERSION; } static get NAME() { throw new Error('You have to implement the static method "NAME", for each component!'); } static get DATA_KEY() { return `bs.${this.NAME}`; } static get EVENT_KEY() { return `.${this.DATA_KEY}`; } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$c = 'alert'; const DATA_KEY$b = 'bs.alert'; const EVENT_KEY$b = `.${DATA_KEY$b}`; const DATA_API_KEY$8 = '.data-api'; const SELECTOR_DISMISS = '[data-bs-dismiss="alert"]'; const EVENT_CLOSE = `close${EVENT_KEY$b}`; const EVENT_CLOSED = `closed${EVENT_KEY$b}`; const EVENT_CLICK_DATA_API$7 = `click${EVENT_KEY$b}${DATA_API_KEY$8}`; const CLASS_NAME_ALERT = 'alert'; const CLASS_NAME_FADE$6 = 'fade'; const CLASS_NAME_SHOW$9 = 'show'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Alert extends BaseComponent { // Getters static get NAME() { return NAME$c; } // Public close(element) { const rootElement = element ? this._getRootElement(element) : this._element; const customEvent = this._triggerCloseEvent(rootElement); if (customEvent === null || customEvent.defaultPrevented) { return; } this._removeElement(rootElement); } // Private _getRootElement(element) { return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`); } _triggerCloseEvent(element) { return EventHandler.trigger(element, EVENT_CLOSE); } _removeElement(element) { element.classList.remove(CLASS_NAME_SHOW$9); const isAnimated = element.classList.contains(CLASS_NAME_FADE$6); this._queueCallback(() => this._destroyElement(element), element, isAnimated); } _destroyElement(element) { element.remove(); EventHandler.trigger(element, EVENT_CLOSED); } // Static static jQueryInterface(config) { return this.each(function () { const data = Alert.getOrCreateInstance(this); if (config === 'close') { data[config](this); } }); } static handleDismiss(alertInstance) { return function (event) { if (event) { event.preventDefault(); } alertInstance.close(this); }; } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_DISMISS, Alert.handleDismiss(new Alert())); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Alert to jQuery only if jQuery is present */ defineJQueryPlugin(Alert); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$b = 'button'; const DATA_KEY$a = 'bs.button'; const EVENT_KEY$a = `.${DATA_KEY$a}`; const DATA_API_KEY$7 = '.data-api'; const CLASS_NAME_ACTIVE$3 = 'active'; const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]'; const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$7}`; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Button extends BaseComponent { // Getters static get NAME() { return NAME$b; } // Public toggle() { // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3)); } // Static static jQueryInterface(config) { return this.each(function () { const data = Button.getOrCreateInstance(this); if (config === 'toggle') { data[config](); } }); } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => { event.preventDefault(); const button = event.target.closest(SELECTOR_DATA_TOGGLE$5); const data = Button.getOrCreateInstance(button); data.toggle(); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Button to jQuery only if jQuery is present */ defineJQueryPlugin(Button); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): dom/manipulator.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ function normalizeData(val) { if (val === 'true') { return true; } if (val === 'false') { return false; } if (val === Number(val).toString()) { return Number(val); } if (val === '' || val === 'null') { return null; } return val; } function normalizeDataKey(key) { return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`); } const Manipulator = { setDataAttribute(element, key, value) { element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); }, removeDataAttribute(element, key) { element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); }, getDataAttributes(element) { if (!element) { return {}; } const attributes = {}; Object.keys(element.dataset).filter(key => key.startsWith('bs')).forEach(key => { let pureKey = key.replace(/^bs/, ''); pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length); attributes[pureKey] = normalizeData(element.dataset[key]); }); return attributes; }, getDataAttribute(element, key) { return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); }, offset(element) { const rect = element.getBoundingClientRect(); return { top: rect.top + document.body.scrollTop, left: rect.left + document.body.scrollLeft }; }, position(element) { return { top: element.offsetTop, left: element.offsetLeft }; } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$a = 'carousel'; const DATA_KEY$9 = 'bs.carousel'; const EVENT_KEY$9 = `.${DATA_KEY$9}`; const DATA_API_KEY$6 = '.data-api'; const ARROW_LEFT_KEY = 'ArrowLeft'; const ARROW_RIGHT_KEY = 'ArrowRight'; const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch const SWIPE_THRESHOLD = 40; const Default$9 = { interval: 5000, keyboard: true, slide: false, pause: 'hover', wrap: true, touch: true }; const DefaultType$9 = { interval: '(number|boolean)', keyboard: 'boolean', slide: '(boolean|string)', pause: '(string|boolean)', wrap: 'boolean', touch: 'boolean' }; const ORDER_NEXT = 'next'; const ORDER_PREV = 'prev'; const DIRECTION_LEFT = 'left'; const DIRECTION_RIGHT = 'right'; const KEY_TO_DIRECTION = { [ARROW_LEFT_KEY]: DIRECTION_RIGHT, [ARROW_RIGHT_KEY]: DIRECTION_LEFT }; const EVENT_SLIDE = `slide${EVENT_KEY$9}`; const EVENT_SLID = `slid${EVENT_KEY$9}`; const EVENT_KEYDOWN = `keydown${EVENT_KEY$9}`; const EVENT_MOUSEENTER = `mouseenter${EVENT_KEY$9}`; const EVENT_MOUSELEAVE = `mouseleave${EVENT_KEY$9}`; const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`; const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`; const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`; const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`; const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`; const EVENT_DRAG_START = `dragstart${EVENT_KEY$9}`; const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$9}${DATA_API_KEY$6}`; const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$9}${DATA_API_KEY$6}`; const CLASS_NAME_CAROUSEL = 'carousel'; const CLASS_NAME_ACTIVE$2 = 'active'; const CLASS_NAME_SLIDE = 'slide'; const CLASS_NAME_END = 'carousel-item-end'; const CLASS_NAME_START = 'carousel-item-start'; const CLASS_NAME_NEXT = 'carousel-item-next'; const CLASS_NAME_PREV = 'carousel-item-prev'; const CLASS_NAME_POINTER_EVENT = 'pointer-event'; const SELECTOR_ACTIVE$1 = '.active'; const SELECTOR_ACTIVE_ITEM = '.active.carousel-item'; const SELECTOR_ITEM = '.carousel-item'; const SELECTOR_ITEM_IMG = '.carousel-item img'; const SELECTOR_NEXT_PREV = '.carousel-item-next, .carousel-item-prev'; const SELECTOR_INDICATORS = '.carousel-indicators'; const SELECTOR_INDICATOR = '[data-bs-target]'; const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'; const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'; const POINTER_TYPE_TOUCH = 'touch'; const POINTER_TYPE_PEN = 'pen'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Carousel extends BaseComponent { constructor(element, config) { super(element); this._items = null; this._interval = null; this._activeElement = null; this._isPaused = false; this._isSliding = false; this.touchTimeout = null; this.touchStartX = 0; this.touchDeltaX = 0; this._config = this._getConfig(config); this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; this._pointerEvent = Boolean(window.PointerEvent); this._addEventListeners(); } // Getters static get Default() { return Default$9; } static get NAME() { return NAME$a; } // Public next() { this._slide(ORDER_NEXT); } nextWhenVisible() { // Don't call next when the page isn't visible // or the carousel or its parent isn't visible if (!document.hidden && isVisible(this._element)) { this.next(); } } prev() { this._slide(ORDER_PREV); } pause(event) { if (!event) { this._isPaused = true; } if (SelectorEngine.findOne(SELECTOR_NEXT_PREV, this._element)) { triggerTransitionEnd(this._element); this.cycle(true); } clearInterval(this._interval); this._interval = null; } cycle(event) { if (!event) { this._isPaused = false; } if (this._interval) { clearInterval(this._interval); this._interval = null; } if (this._config && this._config.interval && !this._isPaused) { this._updateInterval(); this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); } } to(index) { this._activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); const activeIndex = this._getItemIndex(this._activeElement); if (index > this._items.length - 1 || index < 0) { return; } if (this._isSliding) { EventHandler.one(this._element, EVENT_SLID, () => this.to(index)); return; } if (activeIndex === index) { this.pause(); this.cycle(); return; } const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV; this._slide(order, this._items[index]); } // Private _getConfig(config) { config = { ...Default$9, ...Manipulator.getDataAttributes(this._element), ...(typeof config === 'object' ? config : {}) }; typeCheckConfig(NAME$a, config, DefaultType$9); return config; } _handleSwipe() { const absDeltax = Math.abs(this.touchDeltaX); if (absDeltax <= SWIPE_THRESHOLD) { return; } const direction = absDeltax / this.touchDeltaX; this.touchDeltaX = 0; if (!direction) { return; } this._slide(direction > 0 ? DIRECTION_RIGHT : DIRECTION_LEFT); } _addEventListeners() { if (this._config.keyboard) { EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event)); } if (this._config.pause === 'hover') { EventHandler.on(this._element, EVENT_MOUSEENTER, event => this.pause(event)); EventHandler.on(this._element, EVENT_MOUSELEAVE, event => this.cycle(event)); } if (this._config.touch && this._touchSupported) { this._addTouchEventListeners(); } } _addTouchEventListeners() { const start = event => { if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) { this.touchStartX = event.clientX; } else if (!this._pointerEvent) { this.touchStartX = event.touches[0].clientX; } }; const move = event => { // ensure swiping with one touch and not pinching this.touchDeltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this.touchStartX; }; const end = event => { if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) { this.touchDeltaX = event.clientX - this.touchStartX; } this._handleSwipe(); if (this._config.pause === 'hover') { // If it's a touch-enabled device, mouseenter/leave are fired as // part of the mouse compatibility events on first tap - the carousel // would stop cycling until user tapped out of it; // here, we listen for touchend, explicitly pause the carousel // (as if it's the second time we tap on it, mouseenter compat event // is NOT fired) and after a timeout (to allow for mouse compatibility // events to fire) we explicitly restart cycling this.pause(); if (this.touchTimeout) { clearTimeout(this.touchTimeout); } this.touchTimeout = setTimeout(event => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval); } }; SelectorEngine.find(SELECTOR_ITEM_IMG, this._element).forEach(itemImg => { EventHandler.on(itemImg, EVENT_DRAG_START, e => e.preventDefault()); }); if (this._pointerEvent) { EventHandler.on(this._element, EVENT_POINTERDOWN, event => start(event)); EventHandler.on(this._element, EVENT_POINTERUP, event => end(event)); this._element.classList.add(CLASS_NAME_POINTER_EVENT); } else { EventHandler.on(this._element, EVENT_TOUCHSTART, event => start(event)); EventHandler.on(this._element, EVENT_TOUCHMOVE, event => move(event)); EventHandler.on(this._element, EVENT_TOUCHEND, event => end(event)); } } _keydown(event) { if (/input|textarea/i.test(event.target.tagName)) { return; } const direction = KEY_TO_DIRECTION[event.key]; if (direction) { event.preventDefault(); this._slide(direction); } } _getItemIndex(element) { this._items = element && element.parentNode ? SelectorEngine.find(SELECTOR_ITEM, element.parentNode) : []; return this._items.indexOf(element); } _getItemByOrder(order, activeElement) { const isNext = order === ORDER_NEXT; return getNextActiveElement(this._items, activeElement, isNext, this._config.wrap); } _triggerSlideEvent(relatedTarget, eventDirectionName) { const targetIndex = this._getItemIndex(relatedTarget); const fromIndex = this._getItemIndex(SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element)); return EventHandler.trigger(this._element, EVENT_SLIDE, { relatedTarget, direction: eventDirectionName, from: fromIndex, to: targetIndex }); } _setActiveIndicatorElement(element) { if (this._indicatorsElement) { const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE$1, this._indicatorsElement); activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2); activeIndicator.removeAttribute('aria-current'); const indicators = SelectorEngine.find(SELECTOR_INDICATOR, this._indicatorsElement); for (let i = 0; i < indicators.length; i++) { if (Number.parseInt(indicators[i].getAttribute('data-bs-slide-to'), 10) === this._getItemIndex(element)) { indicators[i].classList.add(CLASS_NAME_ACTIVE$2); indicators[i].setAttribute('aria-current', 'true'); break; } } } } _updateInterval() { const element = this._activeElement || SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); if (!element) { return; } const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10); if (elementInterval) { this._config.defaultInterval = this._config.defaultInterval || this._config.interval; this._config.interval = elementInterval; } else { this._config.interval = this._config.defaultInterval || this._config.interval; } } _slide(directionOrOrder, element) { const order = this._directionToOrder(directionOrOrder); const activeElement = SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); const activeElementIndex = this._getItemIndex(activeElement); const nextElement = element || this._getItemByOrder(order, activeElement); const nextElementIndex = this._getItemIndex(nextElement); const isCycling = Boolean(this._interval); const isNext = order === ORDER_NEXT; const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END; const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV; const eventDirectionName = this._orderToDirection(order); if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE$2)) { this._isSliding = false; return; } if (this._isSliding) { return; } const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); if (slideEvent.defaultPrevented) { return; } if (!activeElement || !nextElement) { // Some weirdness is happening, so we bail return; } this._isSliding = true; if (isCycling) { this.pause(); } this._setActiveIndicatorElement(nextElement); this._activeElement = nextElement; const triggerSlidEvent = () => { EventHandler.trigger(this._element, EVENT_SLID, { relatedTarget: nextElement, direction: eventDirectionName, from: activeElementIndex, to: nextElementIndex }); }; if (this._element.classList.contains(CLASS_NAME_SLIDE)) { nextElement.classList.add(orderClassName); reflow(nextElement); activeElement.classList.add(directionalClassName); nextElement.classList.add(directionalClassName); const completeCallBack = () => { nextElement.classList.remove(directionalClassName, orderClassName); nextElement.classList.add(CLASS_NAME_ACTIVE$2); activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName); this._isSliding = false; setTimeout(triggerSlidEvent, 0); }; this._queueCallback(completeCallBack, activeElement, true); } else { activeElement.classList.remove(CLASS_NAME_ACTIVE$2); nextElement.classList.add(CLASS_NAME_ACTIVE$2); this._isSliding = false; triggerSlidEvent(); } if (isCycling) { this.cycle(); } } _directionToOrder(direction) { if (![DIRECTION_RIGHT, DIRECTION_LEFT].includes(direction)) { return direction; } if (isRTL()) { return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT; } return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV; } _orderToDirection(order) { if (![ORDER_NEXT, ORDER_PREV].includes(order)) { return order; } if (isRTL()) { return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT; } return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT; } // Static static carouselInterface(element, config) { const data = Carousel.getOrCreateInstance(element, config); let { _config } = data; if (typeof config === 'object') { _config = { ..._config, ...config }; } const action = typeof config === 'string' ? config : _config.slide; if (typeof config === 'number') { data.to(config); } else if (typeof action === 'string') { if (typeof data[action] === 'undefined') { throw new TypeError(`No method named "${action}"`); } data[action](); } else if (_config.interval && _config.ride) { data.pause(); data.cycle(); } } static jQueryInterface(config) { return this.each(function () { Carousel.carouselInterface(this, config); }); } static dataApiClickHandler(event) { const target = getElementFromSelector(this); if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) { return; } const config = { ...Manipulator.getDataAttributes(target), ...Manipulator.getDataAttributes(this) }; const slideIndex = this.getAttribute('data-bs-slide-to'); if (slideIndex) { config.interval = false; } Carousel.carouselInterface(target, config); if (slideIndex) { Carousel.getInstance(target).to(slideIndex); } event.preventDefault(); } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, Carousel.dataApiClickHandler); EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => { const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); for (let i = 0, len = carousels.length; i < len; i++) { Carousel.carouselInterface(carousels[i], Carousel.getInstance(carousels[i])); } }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Carousel to jQuery only if jQuery is present */ defineJQueryPlugin(Carousel); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$9 = 'collapse'; const DATA_KEY$8 = 'bs.collapse'; const EVENT_KEY$8 = `.${DATA_KEY$8}`; const DATA_API_KEY$5 = '.data-api'; const Default$8 = { toggle: true, parent: '' }; const DefaultType$8 = { toggle: 'boolean', parent: '(string|element)' }; const EVENT_SHOW$5 = `show${EVENT_KEY$8}`; const EVENT_SHOWN$5 = `shown${EVENT_KEY$8}`; const EVENT_HIDE$5 = `hide${EVENT_KEY$8}`; const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$8}`; const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`; const CLASS_NAME_SHOW$8 = 'show'; const CLASS_NAME_COLLAPSE = 'collapse'; const CLASS_NAME_COLLAPSING = 'collapsing'; const CLASS_NAME_COLLAPSED = 'collapsed'; const WIDTH = 'width'; const HEIGHT = 'height'; const SELECTOR_ACTIVES = '.show, .collapsing'; const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Collapse extends BaseComponent { constructor(element, config) { super(element); this._isTransitioning = false; this._config = this._getConfig(config); this._triggerArray = SelectorEngine.find(`${SELECTOR_DATA_TOGGLE$4}[href="#${this._element.id}"],` + `${SELECTOR_DATA_TOGGLE$4}[data-bs-target="#${this._element.id}"]`); const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4); for (let i = 0, len = toggleList.length; i < len; i++) { const elem = toggleList[i]; const selector = getSelectorFromElement(elem); const filterElement = SelectorEngine.find(selector).filter(foundElem => foundElem === this._element); if (selector !== null && filterElement.length) { this._selector = selector; this._triggerArray.push(elem); } } this._parent = this._config.parent ? this._getParent() : null; if (!this._config.parent) { this._addAriaAndCollapsedClass(this._element, this._triggerArray); } if (this._config.toggle) { this.toggle(); } } // Getters static get Default() { return Default$8; } static get NAME() { return NAME$9; } // Public toggle() { if (this._element.classList.contains(CLASS_NAME_SHOW$8)) { this.hide(); } else { this.show(); } } show() { if (this._isTransitioning || this._element.classList.contains(CLASS_NAME_SHOW$8)) { return; } let actives; let activesData; if (this._parent) { actives = SelectorEngine.find(SELECTOR_ACTIVES, this._parent).filter(elem => { if (typeof this._config.parent === 'string') { return elem.getAttribute('data-bs-parent') === this._config.parent; } return elem.classList.contains(CLASS_NAME_COLLAPSE); }); if (actives.length === 0) { actives = null; } } const container = SelectorEngine.findOne(this._selector); if (actives) { const tempActiveData = actives.find(elem => container !== elem); activesData = tempActiveData ? Collapse.getInstance(tempActiveData) : null; if (activesData && activesData._isTransitioning) { return; } } const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$5); if (startEvent.defaultPrevented) { return; } if (actives) { actives.forEach(elemActive => { if (container !== elemActive) { Collapse.collapseInterface(elemActive, 'hide'); } if (!activesData) { Data.set(elemActive, DATA_KEY$8, null); } }); } const dimension = this._getDimension(); this._element.classList.remove(CLASS_NAME_COLLAPSE); this._element.classList.add(CLASS_NAME_COLLAPSING); this._element.style[dimension] = 0; if (this._triggerArray.length) { this._triggerArray.forEach(element => { element.classList.remove(CLASS_NAME_COLLAPSED); element.setAttribute('aria-expanded', true); }); } this.setTransitioning(true); const complete = () => { this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$8); this._element.style[dimension] = ''; this.setTransitioning(false); EventHandler.trigger(this._element, EVENT_SHOWN$5); }; const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); const scrollSize = `scroll${capitalizedDimension}`; this._queueCallback(complete, this._element, true); this._element.style[dimension] = `${this._element[scrollSize]}px`; } hide() { if (this._isTransitioning || !this._element.classList.contains(CLASS_NAME_SHOW$8)) { return; } const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$5); if (startEvent.defaultPrevented) { return; } const dimension = this._getDimension(); this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`; reflow(this._element); this._element.classList.add(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$8); const triggerArrayLength = this._triggerArray.length; if (triggerArrayLength > 0) { for (let i = 0; i < triggerArrayLength; i++) { const trigger = this._triggerArray[i]; const elem = getElementFromSelector(trigger); if (elem && !elem.classList.contains(CLASS_NAME_SHOW$8)) { trigger.classList.add(CLASS_NAME_COLLAPSED); trigger.setAttribute('aria-expanded', false); } } } this.setTransitioning(true); const complete = () => { this.setTransitioning(false); this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.add(CLASS_NAME_COLLAPSE); EventHandler.trigger(this._element, EVENT_HIDDEN$5); }; this._element.style[dimension] = ''; this._queueCallback(complete, this._element, true); } setTransitioning(isTransitioning) { this._isTransitioning = isTransitioning; } // Private _getConfig(config) { config = { ...Default$8, ...config }; config.toggle = Boolean(config.toggle); // Coerce string values typeCheckConfig(NAME$9, config, DefaultType$8); return config; } _getDimension() { return this._element.classList.contains(WIDTH) ? WIDTH : HEIGHT; } _getParent() { let { parent } = this._config; parent = getElement(parent); const selector = `${SELECTOR_DATA_TOGGLE$4}[data-bs-parent="${parent}"]`; SelectorEngine.find(selector, parent).forEach(element => { const selected = getElementFromSelector(element); this._addAriaAndCollapsedClass(selected, [element]); }); return parent; } _addAriaAndCollapsedClass(element, triggerArray) { if (!element || !triggerArray.length) { return; } const isOpen = element.classList.contains(CLASS_NAME_SHOW$8); triggerArray.forEach(elem => { if (isOpen) { elem.classList.remove(CLASS_NAME_COLLAPSED); } else { elem.classList.add(CLASS_NAME_COLLAPSED); } elem.setAttribute('aria-expanded', isOpen); }); } // Static static collapseInterface(element, config) { let data = Collapse.getInstance(element); const _config = { ...Default$8, ...Manipulator.getDataAttributes(element), ...(typeof config === 'object' && config ? config : {}) }; if (!data && _config.toggle && typeof config === 'string' && /show|hide/.test(config)) { _config.toggle = false; } if (!data) { data = new Collapse(element, _config); } if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } } static jQueryInterface(config) { return this.each(function () { Collapse.collapseInterface(this, config); }); } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') { event.preventDefault(); } const triggerData = Manipulator.getDataAttributes(this); const selector = getSelectorFromElement(this); const selectorElements = SelectorEngine.find(selector); selectorElements.forEach(element => { const data = Collapse.getInstance(element); let config; if (data) { // update parent attribute if (data._parent === null && typeof triggerData.parent === 'string') { data._config.parent = triggerData.parent; data._parent = data._getParent(); } config = 'toggle'; } else { config = triggerData; } Collapse.collapseInterface(element, config); }); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Collapse to jQuery only if jQuery is present */ defineJQueryPlugin(Collapse); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$8 = 'dropdown'; const DATA_KEY$7 = 'bs.dropdown'; const EVENT_KEY$7 = `.${DATA_KEY$7}`; const DATA_API_KEY$4 = '.data-api'; const ESCAPE_KEY$2 = 'Escape'; const SPACE_KEY = 'Space'; const TAB_KEY = 'Tab'; const ARROW_UP_KEY = 'ArrowUp'; const ARROW_DOWN_KEY = 'ArrowDown'; const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEY}|${ARROW_DOWN_KEY}|${ESCAPE_KEY$2}`); const EVENT_HIDE$4 = `hide${EVENT_KEY$7}`; const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$7}`; const EVENT_SHOW$4 = `show${EVENT_KEY$7}`; const EVENT_SHOWN$4 = `shown${EVENT_KEY$7}`; const EVENT_CLICK = `click${EVENT_KEY$7}`; const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`; const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$7}${DATA_API_KEY$4}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$7}${DATA_API_KEY$4}`; const CLASS_NAME_SHOW$7 = 'show'; const CLASS_NAME_DROPUP = 'dropup'; const CLASS_NAME_DROPEND = 'dropend'; const CLASS_NAME_DROPSTART = 'dropstart'; const CLASS_NAME_NAVBAR = 'navbar'; const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]'; const SELECTOR_MENU = '.dropdown-menu'; const SELECTOR_NAVBAR_NAV = '.navbar-nav'; const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'; const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'; const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'; const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'; const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'; const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'; const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'; const Default$7 = { offset: [0, 2], boundary: 'clippingParents', reference: 'toggle', display: 'dynamic', popperConfig: null, autoClose: true }; const DefaultType$7 = { offset: '(array|string|function)', boundary: '(string|element)', reference: '(string|element|object)', display: 'string', popperConfig: '(null|object|function)', autoClose: '(boolean|string)' }; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Dropdown extends BaseComponent { constructor(element, config) { super(element); this._popper = null; this._config = this._getConfig(config); this._menu = this._getMenuElement(); this._inNavbar = this._detectNavbar(); this._addEventListeners(); } // Getters static get Default() { return Default$7; } static get DefaultType() { return DefaultType$7; } static get NAME() { return NAME$8; } // Public toggle() { if (isDisabled(this._element)) { return; } const isActive = this._element.classList.contains(CLASS_NAME_SHOW$7); if (isActive) { this.hide(); return; } this.show(); } show() { if (isDisabled(this._element) || this._menu.classList.contains(CLASS_NAME_SHOW$7)) { return; } const parent = Dropdown.getParentFromElement(this._element); const relatedTarget = { relatedTarget: this._element }; const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, relatedTarget); if (showEvent.defaultPrevented) { return; } // Totally disable Popper for Dropdowns in Navbar if (this._inNavbar) { Manipulator.setDataAttribute(this._menu, 'popper', 'none'); } else { if (typeof Popper__namespace === 'undefined') { throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)'); } let referenceElement = this._element; if (this._config.reference === 'parent') { referenceElement = parent; } else if (isElement(this._config.reference)) { referenceElement = getElement(this._config.reference); } else if (typeof this._config.reference === 'object') { referenceElement = this._config.reference; } const popperConfig = this._getPopperConfig(); const isDisplayStatic = popperConfig.modifiers.find(modifier => modifier.name === 'applyStyles' && modifier.enabled === false); this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig); if (isDisplayStatic) { Manipulator.setDataAttribute(this._menu, 'popper', 'static'); } } // If this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement && !parent.closest(SELECTOR_NAVBAR_NAV)) { [].concat(...document.body.children).forEach(elem => EventHandler.on(elem, 'mouseover', noop)); } this._element.focus(); this._element.setAttribute('aria-expanded', true); this._menu.classList.toggle(CLASS_NAME_SHOW$7); this._element.classList.toggle(CLASS_NAME_SHOW$7); EventHandler.trigger(this._element, EVENT_SHOWN$4, relatedTarget); } hide() { if (isDisabled(this._element) || !this._menu.classList.contains(CLASS_NAME_SHOW$7)) { return; } const relatedTarget = { relatedTarget: this._element }; this._completeHide(relatedTarget); } dispose() { if (this._popper) { this._popper.destroy(); } super.dispose(); } update() { this._inNavbar = this._detectNavbar(); if (this._popper) { this._popper.update(); } } // Private _addEventListeners() { EventHandler.on(this._element, EVENT_CLICK, event => { event.preventDefault(); this.toggle(); }); } _completeHide(relatedTarget) { const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4, relatedTarget); if (hideEvent.defaultPrevented) { return; } // If this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { [].concat(...document.body.children).forEach(elem => EventHandler.off(elem, 'mouseover', noop)); } if (this._popper) { this._popper.destroy(); } this._menu.classList.remove(CLASS_NAME_SHOW$7); this._element.classList.remove(CLASS_NAME_SHOW$7); this._element.setAttribute('aria-expanded', 'false'); Manipulator.removeDataAttribute(this._menu, 'popper'); EventHandler.trigger(this._element, EVENT_HIDDEN$4, relatedTarget); } _getConfig(config) { config = { ...this.constructor.Default, ...Manipulator.getDataAttributes(this._element), ...config }; typeCheckConfig(NAME$8, config, this.constructor.DefaultType); if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') { // Popper virtual elements require a getBoundingClientRect method throw new TypeError(`${NAME$8.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); } return config; } _getMenuElement() { return SelectorEngine.next(this._element, SELECTOR_MENU)[0]; } _getPlacement() { const parentDropdown = this._element.parentNode; if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { return PLACEMENT_RIGHT; } if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { return PLACEMENT_LEFT; } // We need to trim the value because custom properties can also include spaces const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'; if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP; } return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM; } _detectNavbar() { return this._element.closest(`.${CLASS_NAME_NAVBAR}`) !== null; } _getOffset() { const { offset } = this._config; if (typeof offset === 'string') { return offset.split(',').map(val => Number.parseInt(val, 10)); } if (typeof offset === 'function') { return popperData => offset(popperData, this._element); } return offset; } _getPopperConfig() { const defaultBsPopperConfig = { placement: this._getPlacement(), modifiers: [{ name: 'preventOverflow', options: { boundary: this._config.boundary } }, { name: 'offset', options: { offset: this._getOffset() } }] }; // Disable Popper if we have a static display if (this._config.display === 'static') { defaultBsPopperConfig.modifiers = [{ name: 'applyStyles', enabled: false }]; } return { ...defaultBsPopperConfig, ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) }; } _selectMenuItem({ key, target }) { const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(isVisible); if (!items.length) { return; } // if target isn't included in items (e.g. when expanding the dropdown) // allow cycling to get the last item in case key equals ARROW_UP_KEY getNextActiveElement(items, target, key === ARROW_DOWN_KEY, !items.includes(target)).focus(); } // Static static dropdownInterface(element, config) { const data = Dropdown.getOrCreateInstance(element, config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } } static jQueryInterface(config) { return this.each(function () { Dropdown.dropdownInterface(this, config); }); } static clearMenus(event) { if (event && (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY)) { return; } const toggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE$3); for (let i = 0, len = toggles.length; i < len; i++) { const context = Dropdown.getInstance(toggles[i]); if (!context || context._config.autoClose === false) { continue; } if (!context._element.classList.contains(CLASS_NAME_SHOW$7)) { continue; } const relatedTarget = { relatedTarget: context._element }; if (event) { const composedPath = event.composedPath(); const isMenuTarget = composedPath.includes(context._menu); if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) { continue; } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY || /input|select|option|textarea|form/i.test(event.target.tagName))) { continue; } if (event.type === 'click') { relatedTarget.clickEvent = event; } } context._completeHide(relatedTarget); } } static getParentFromElement(element) { return getElementFromSelector(element) || element.parentNode; } static dataApiKeydownHandler(event) { // If not input/textarea: // - And not a key in REGEXP_KEYDOWN => not a dropdown command // If input/textarea: // - If space key => not a dropdown command // - If key is other than escape // - If key is not up or down => not a dropdown command // - If trigger inside the menu => not a dropdown command if (/input|textarea/i.test(event.target.tagName) ? event.key === SPACE_KEY || event.key !== ESCAPE_KEY$2 && (event.key !== ARROW_DOWN_KEY && event.key !== ARROW_UP_KEY || event.target.closest(SELECTOR_MENU)) : !REGEXP_KEYDOWN.test(event.key)) { return; } const isActive = this.classList.contains(CLASS_NAME_SHOW$7); if (!isActive && event.key === ESCAPE_KEY$2) { return; } event.preventDefault(); event.stopPropagation(); if (isDisabled(this)) { return; } const getToggleButton = () => this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0]; if (event.key === ESCAPE_KEY$2) { getToggleButton().focus(); Dropdown.clearMenus(); return; } if (event.key === ARROW_UP_KEY || event.key === ARROW_DOWN_KEY) { if (!isActive) { getToggleButton().click(); } Dropdown.getInstance(getToggleButton())._selectMenuItem(event); return; } if (!isActive || event.key === SPACE_KEY) { Dropdown.clearMenus(); } } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler); EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler); EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus); EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) { event.preventDefault(); Dropdown.dropdownInterface(this); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Dropdown to jQuery only if jQuery is present */ defineJQueryPlugin(Dropdown); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): util/scrollBar.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; const SELECTOR_STICKY_CONTENT = '.sticky-top'; class ScrollBarHelper { constructor() { this._element = document.body; } getWidth() { // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes const documentWidth = document.documentElement.clientWidth; return Math.abs(window.innerWidth - documentWidth); } hide() { const width = this.getWidth(); this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width this._setElementAttributes(this._element, 'paddingRight', calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth this._setElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight', calculatedValue => calculatedValue + width); this._setElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight', calculatedValue => calculatedValue - width); } _disableOverFlow() { this._saveInitialAttribute(this._element, 'overflow'); this._element.style.overflow = 'hidden'; } _setElementAttributes(selector, styleProp, callback) { const scrollbarWidth = this.getWidth(); const manipulationCallBack = element => { if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { return; } this._saveInitialAttribute(element, styleProp); const calculatedValue = window.getComputedStyle(element)[styleProp]; element.style[styleProp] = `${callback(Number.parseFloat(calculatedValue))}px`; }; this._applyManipulationCallback(selector, manipulationCallBack); } reset() { this._resetElementAttributes(this._element, 'overflow'); this._resetElementAttributes(this._element, 'paddingRight'); this._resetElementAttributes(SELECTOR_FIXED_CONTENT, 'paddingRight'); this._resetElementAttributes(SELECTOR_STICKY_CONTENT, 'marginRight'); } _saveInitialAttribute(element, styleProp) { const actualValue = element.style[styleProp]; if (actualValue) { Manipulator.setDataAttribute(element, styleProp, actualValue); } } _resetElementAttributes(selector, styleProp) { const manipulationCallBack = element => { const value = Manipulator.getDataAttribute(element, styleProp); if (typeof value === 'undefined') { element.style.removeProperty(styleProp); } else { Manipulator.removeDataAttribute(element, styleProp); element.style[styleProp] = value; } }; this._applyManipulationCallback(selector, manipulationCallBack); } _applyManipulationCallback(selector, callBack) { if (isElement(selector)) { callBack(selector); } else { SelectorEngine.find(selector, this._element).forEach(callBack); } } isOverflowing() { return this.getWidth() > 0; } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): util/backdrop.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ const Default$6 = { isVisible: true, // if false, we use the backdrop helper without adding any element to the dom isAnimated: false, rootElement: 'body', // give the choice to place backdrop under different elements clickCallback: null }; const DefaultType$6 = { isVisible: 'boolean', isAnimated: 'boolean', rootElement: '(element|string)', clickCallback: '(function|null)' }; const NAME$7 = 'backdrop'; const CLASS_NAME_BACKDROP = 'modal-backdrop'; const CLASS_NAME_FADE$5 = 'fade'; const CLASS_NAME_SHOW$6 = 'show'; const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$7}`; class Backdrop { constructor(config) { this._config = this._getConfig(config); this._isAppended = false; this._element = null; } show(callback) { if (!this._config.isVisible) { execute(callback); return; } this._append(); if (this._config.isAnimated) { reflow(this._getElement()); } this._getElement().classList.add(CLASS_NAME_SHOW$6); this._emulateAnimation(() => { execute(callback); }); } hide(callback) { if (!this._config.isVisible) { execute(callback); return; } this._getElement().classList.remove(CLASS_NAME_SHOW$6); this._emulateAnimation(() => { this.dispose(); execute(callback); }); } // Private _getElement() { if (!this._element) { const backdrop = document.createElement('div'); backdrop.className = CLASS_NAME_BACKDROP; if (this._config.isAnimated) { backdrop.classList.add(CLASS_NAME_FADE$5); } this._element = backdrop; } return this._element; } _getConfig(config) { config = { ...Default$6, ...(typeof config === 'object' ? config : {}) }; // use getElement() with the default "body" to get a fresh Element on each instantiation config.rootElement = getElement(config.rootElement); typeCheckConfig(NAME$7, config, DefaultType$6); return config; } _append() { if (this._isAppended) { return; } this._config.rootElement.appendChild(this._getElement()); EventHandler.on(this._getElement(), EVENT_MOUSEDOWN, () => { execute(this._config.clickCallback); }); this._isAppended = true; } dispose() { if (!this._isAppended) { return; } EventHandler.off(this._element, EVENT_MOUSEDOWN); this._element.remove(); this._isAppended = false; } _emulateAnimation(callback) { executeAfterTransition(callback, this._getElement(), this._config.isAnimated); } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$6 = 'modal'; const DATA_KEY$6 = 'bs.modal'; const EVENT_KEY$6 = `.${DATA_KEY$6}`; const DATA_API_KEY$3 = '.data-api'; const ESCAPE_KEY$1 = 'Escape'; const Default$5 = { backdrop: true, keyboard: true, focus: true }; const DefaultType$5 = { backdrop: '(boolean|string)', keyboard: 'boolean', focus: 'boolean' }; const EVENT_HIDE$3 = `hide${EVENT_KEY$6}`; const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$6}`; const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$6}`; const EVENT_SHOW$3 = `show${EVENT_KEY$6}`; const EVENT_SHOWN$3 = `shown${EVENT_KEY$6}`; const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$6}`; const EVENT_RESIZE = `resize${EVENT_KEY$6}`; const EVENT_CLICK_DISMISS$2 = `click.dismiss${EVENT_KEY$6}`; const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$6}`; const EVENT_MOUSEUP_DISMISS = `mouseup.dismiss${EVENT_KEY$6}`; const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$6}`; const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`; const CLASS_NAME_OPEN = 'modal-open'; const CLASS_NAME_FADE$4 = 'fade'; const CLASS_NAME_SHOW$5 = 'show'; const CLASS_NAME_STATIC = 'modal-static'; const SELECTOR_DIALOG = '.modal-dialog'; const SELECTOR_MODAL_BODY = '.modal-body'; const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]'; const SELECTOR_DATA_DISMISS$2 = '[data-bs-dismiss="modal"]'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Modal extends BaseComponent { constructor(element, config) { super(element); this._config = this._getConfig(config); this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); this._backdrop = this._initializeBackDrop(); this._isShown = false; this._ignoreBackdropClick = false; this._isTransitioning = false; this._scrollBar = new ScrollBarHelper(); } // Getters static get Default() { return Default$5; } static get NAME() { return NAME$6; } // Public toggle(relatedTarget) { return this._isShown ? this.hide() : this.show(relatedTarget); } show(relatedTarget) { if (this._isShown || this._isTransitioning) { return; } const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, { relatedTarget }); if (showEvent.defaultPrevented) { return; } this._isShown = true; if (this._isAnimated()) { this._isTransitioning = true; } this._scrollBar.hide(); document.body.classList.add(CLASS_NAME_OPEN); this._adjustDialog(); this._setEscapeEvent(); this._setResizeEvent(); EventHandler.on(this._element, EVENT_CLICK_DISMISS$2, SELECTOR_DATA_DISMISS$2, event => this.hide(event)); EventHandler.on(this._dialog, EVENT_MOUSEDOWN_DISMISS, () => { EventHandler.one(this._element, EVENT_MOUSEUP_DISMISS, event => { if (event.target === this._element) { this._ignoreBackdropClick = true; } }); }); this._showBackdrop(() => this._showElement(relatedTarget)); } hide(event) { if (event && ['A', 'AREA'].includes(event.target.tagName)) { event.preventDefault(); } if (!this._isShown || this._isTransitioning) { return; } const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3); if (hideEvent.defaultPrevented) { return; } this._isShown = false; const isAnimated = this._isAnimated(); if (isAnimated) { this._isTransitioning = true; } this._setEscapeEvent(); this._setResizeEvent(); EventHandler.off(document, EVENT_FOCUSIN$2); this._element.classList.remove(CLASS_NAME_SHOW$5); EventHandler.off(this._element, EVENT_CLICK_DISMISS$2); EventHandler.off(this._dialog, EVENT_MOUSEDOWN_DISMISS); this._queueCallback(() => this._hideModal(), this._element, isAnimated); } dispose() { [window, this._dialog].forEach(htmlElement => EventHandler.off(htmlElement, EVENT_KEY$6)); this._backdrop.dispose(); super.dispose(); /** * `document` has 2 events `EVENT_FOCUSIN` and `EVENT_CLICK_DATA_API` * Do not move `document` in `htmlElements` array * It will remove `EVENT_CLICK_DATA_API` event that should remain */ EventHandler.off(document, EVENT_FOCUSIN$2); } handleUpdate() { this._adjustDialog(); } // Private _initializeBackDrop() { return new Backdrop({ isVisible: Boolean(this._config.backdrop), // 'static' option will be translated to true, and booleans will keep their value isAnimated: this._isAnimated() }); } _getConfig(config) { config = { ...Default$5, ...Manipulator.getDataAttributes(this._element), ...(typeof config === 'object' ? config : {}) }; typeCheckConfig(NAME$6, config, DefaultType$5); return config; } _showElement(relatedTarget) { const isAnimated = this._isAnimated(); const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { // Don't move modal's DOM position document.body.appendChild(this._element); } this._element.style.display = 'block'; this._element.removeAttribute('aria-hidden'); this._element.setAttribute('aria-modal', true); this._element.setAttribute('role', 'dialog'); this._element.scrollTop = 0; if (modalBody) { modalBody.scrollTop = 0; } if (isAnimated) { reflow(this._element); } this._element.classList.add(CLASS_NAME_SHOW$5); if (this._config.focus) { this._enforceFocus(); } const transitionComplete = () => { if (this._config.focus) { this._element.focus(); } this._isTransitioning = false; EventHandler.trigger(this._element, EVENT_SHOWN$3, { relatedTarget }); }; this._queueCallback(transitionComplete, this._dialog, isAnimated); } _enforceFocus() { EventHandler.off(document, EVENT_FOCUSIN$2); // guard against infinite focus loop EventHandler.on(document, EVENT_FOCUSIN$2, event => { if (document !== event.target && this._element !== event.target && !this._element.contains(event.target)) { this._element.focus(); } }); } _setEscapeEvent() { if (this._isShown) { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => { if (this._config.keyboard && event.key === ESCAPE_KEY$1) { event.preventDefault(); this.hide(); } else if (!this._config.keyboard && event.key === ESCAPE_KEY$1) { this._triggerBackdropTransition(); } }); } else { EventHandler.off(this._element, EVENT_KEYDOWN_DISMISS$1); } } _setResizeEvent() { if (this._isShown) { EventHandler.on(window, EVENT_RESIZE, () => this._adjustDialog()); } else { EventHandler.off(window, EVENT_RESIZE); } } _hideModal() { this._element.style.display = 'none'; this._element.setAttribute('aria-hidden', true); this._element.removeAttribute('aria-modal'); this._element.removeAttribute('role'); this._isTransitioning = false; this._backdrop.hide(() => { document.body.classList.remove(CLASS_NAME_OPEN); this._resetAdjustments(); this._scrollBar.reset(); EventHandler.trigger(this._element, EVENT_HIDDEN$3); }); } _showBackdrop(callback) { EventHandler.on(this._element, EVENT_CLICK_DISMISS$2, event => { if (this._ignoreBackdropClick) { this._ignoreBackdropClick = false; return; } if (event.target !== event.currentTarget) { return; } if (this._config.backdrop === true) { this.hide(); } else if (this._config.backdrop === 'static') { this._triggerBackdropTransition(); } }); this._backdrop.show(callback); } _isAnimated() { return this._element.classList.contains(CLASS_NAME_FADE$4); } _triggerBackdropTransition() { const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); if (hideEvent.defaultPrevented) { return; } const { classList, scrollHeight, style } = this._element; const isModalOverflowing = scrollHeight > document.documentElement.clientHeight; // return if the following background transition hasn't yet completed if (!isModalOverflowing && style.overflowY === 'hidden' || classList.contains(CLASS_NAME_STATIC)) { return; } if (!isModalOverflowing) { style.overflowY = 'hidden'; } classList.add(CLASS_NAME_STATIC); this._queueCallback(() => { classList.remove(CLASS_NAME_STATIC); if (!isModalOverflowing) { this._queueCallback(() => { style.overflowY = ''; }, this._dialog); } }, this._dialog); this._element.focus(); } // ---------------------------------------------------------------------- // the following methods are used to handle overflowing modals // ---------------------------------------------------------------------- _adjustDialog() { const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const scrollbarWidth = this._scrollBar.getWidth(); const isBodyOverflowing = scrollbarWidth > 0; if (!isBodyOverflowing && isModalOverflowing && !isRTL() || isBodyOverflowing && !isModalOverflowing && isRTL()) { this._element.style.paddingLeft = `${scrollbarWidth}px`; } if (isBodyOverflowing && !isModalOverflowing && !isRTL() || !isBodyOverflowing && isModalOverflowing && isRTL()) { this._element.style.paddingRight = `${scrollbarWidth}px`; } } _resetAdjustments() { this._element.style.paddingLeft = ''; this._element.style.paddingRight = ''; } // Static static jQueryInterface(config, relatedTarget) { return this.each(function () { const data = Modal.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](relatedTarget); }); } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) { const target = getElementFromSelector(this); if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault(); } EventHandler.one(target, EVENT_SHOW$3, showEvent => { if (showEvent.defaultPrevented) { // only register focus restorer if modal will actually get shown return; } EventHandler.one(target, EVENT_HIDDEN$3, () => { if (isVisible(this)) { this.focus(); } }); }); const data = Modal.getOrCreateInstance(target); data.toggle(this); }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Modal to jQuery only if jQuery is present */ defineJQueryPlugin(Modal); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): offcanvas.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$5 = 'offcanvas'; const DATA_KEY$5 = 'bs.offcanvas'; const EVENT_KEY$5 = `.${DATA_KEY$5}`; const DATA_API_KEY$2 = '.data-api'; const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$5}${DATA_API_KEY$2}`; const ESCAPE_KEY = 'Escape'; const Default$4 = { backdrop: true, keyboard: true, scroll: false }; const DefaultType$4 = { backdrop: 'boolean', keyboard: 'boolean', scroll: 'boolean' }; const CLASS_NAME_SHOW$4 = 'show'; const OPEN_SELECTOR = '.offcanvas.show'; const EVENT_SHOW$2 = `show${EVENT_KEY$5}`; const EVENT_SHOWN$2 = `shown${EVENT_KEY$5}`; const EVENT_HIDE$2 = `hide${EVENT_KEY$5}`; const EVENT_HIDDEN$2 = `hidden${EVENT_KEY$5}`; const EVENT_FOCUSIN$1 = `focusin${EVENT_KEY$5}`; const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$5}${DATA_API_KEY$2}`; const EVENT_CLICK_DISMISS$1 = `click.dismiss${EVENT_KEY$5}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$5}`; const SELECTOR_DATA_DISMISS$1 = '[data-bs-dismiss="offcanvas"]'; const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Offcanvas extends BaseComponent { constructor(element, config) { super(element); this._config = this._getConfig(config); this._isShown = false; this._backdrop = this._initializeBackDrop(); this._addEventListeners(); } // Getters static get NAME() { return NAME$5; } static get Default() { return Default$4; } // Public toggle(relatedTarget) { return this._isShown ? this.hide() : this.show(relatedTarget); } show(relatedTarget) { if (this._isShown) { return; } const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$2, { relatedTarget }); if (showEvent.defaultPrevented) { return; } this._isShown = true; this._element.style.visibility = 'visible'; this._backdrop.show(); if (!this._config.scroll) { new ScrollBarHelper().hide(); this._enforceFocusOnElement(this._element); } this._element.removeAttribute('aria-hidden'); this._element.setAttribute('aria-modal', true); this._element.setAttribute('role', 'dialog'); this._element.classList.add(CLASS_NAME_SHOW$4); const completeCallBack = () => { EventHandler.trigger(this._element, EVENT_SHOWN$2, { relatedTarget }); }; this._queueCallback(completeCallBack, this._element, true); } hide() { if (!this._isShown) { return; } const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$2); if (hideEvent.defaultPrevented) { return; } EventHandler.off(document, EVENT_FOCUSIN$1); this._element.blur(); this._isShown = false; this._element.classList.remove(CLASS_NAME_SHOW$4); this._backdrop.hide(); const completeCallback = () => { this._element.setAttribute('aria-hidden', true); this._element.removeAttribute('aria-modal'); this._element.removeAttribute('role'); this._element.style.visibility = 'hidden'; if (!this._config.scroll) { new ScrollBarHelper().reset(); } EventHandler.trigger(this._element, EVENT_HIDDEN$2); }; this._queueCallback(completeCallback, this._element, true); } dispose() { this._backdrop.dispose(); super.dispose(); EventHandler.off(document, EVENT_FOCUSIN$1); } // Private _getConfig(config) { config = { ...Default$4, ...Manipulator.getDataAttributes(this._element), ...(typeof config === 'object' ? config : {}) }; typeCheckConfig(NAME$5, config, DefaultType$4); return config; } _initializeBackDrop() { return new Backdrop({ isVisible: this._config.backdrop, isAnimated: true, rootElement: this._element.parentNode, clickCallback: () => this.hide() }); } _enforceFocusOnElement(element) { EventHandler.off(document, EVENT_FOCUSIN$1); // guard against infinite focus loop EventHandler.on(document, EVENT_FOCUSIN$1, event => { if (document !== event.target && element !== event.target && !element.contains(event.target)) { element.focus(); } }); element.focus(); } _addEventListeners() { EventHandler.on(this._element, EVENT_CLICK_DISMISS$1, SELECTOR_DATA_DISMISS$1, () => this.hide()); EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { if (this._config.keyboard && event.key === ESCAPE_KEY) { this.hide(); } }); } // Static static jQueryInterface(config) { return this.each(function () { const data = Offcanvas.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { throw new TypeError(`No method named "${config}"`); } data[config](this); }); } } /** * ------------------------------------------------------------------------ * Data Api implementation * ------------------------------------------------------------------------ */ EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) { const target = getElementFromSelector(this); if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault(); } if (isDisabled(this)) { return; } EventHandler.one(target, EVENT_HIDDEN$2, () => { // focus on trigger when it is closed if (isVisible(this)) { this.focus(); } }); // avoid conflict when clicking a toggler of an offcanvas, while another is open const allReadyOpen = SelectorEngine.findOne(OPEN_SELECTOR); if (allReadyOpen && allReadyOpen !== target) { Offcanvas.getInstance(allReadyOpen).hide(); } const data = Offcanvas.getOrCreateInstance(target); data.toggle(this); }); EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => SelectorEngine.find(OPEN_SELECTOR).forEach(el => Offcanvas.getOrCreateInstance(el).show())); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ defineJQueryPlugin(Offcanvas); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): util/sanitizer.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const uriAttrs = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; /** * A pattern that recognizes a commonly useful subset of URLs that are safe. * * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^#&/:?]*(?:[#/?]|$))/i; /** * A pattern that matches safe data URLs. Only matches image, video and audio types. * * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts */ const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; const allowedAttribute = (attr, allowedAttributeList) => { const attrName = attr.nodeName.toLowerCase(); if (allowedAttributeList.includes(attrName)) { if (uriAttrs.has(attrName)) { return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue)); } return true; } const regExp = allowedAttributeList.filter(attrRegex => attrRegex instanceof RegExp); // Check if a regular expression validates the attribute. for (let i = 0, len = regExp.length; i < len; i++) { if (regExp[i].test(attrName)) { return true; } } return false; }; const DefaultAllowlist = { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], a: ['target', 'href', 'title', 'rel'], area: [], b: [], br: [], col: [], code: [], div: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] }; function sanitizeHtml(unsafeHtml, allowList, sanitizeFn) { if (!unsafeHtml.length) { return unsafeHtml; } if (sanitizeFn && typeof sanitizeFn === 'function') { return sanitizeFn(unsafeHtml); } const domParser = new window.DOMParser(); const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); const allowlistKeys = Object.keys(allowList); const elements = [].concat(...createdDocument.body.querySelectorAll('*')); for (let i = 0, len = elements.length; i < len; i++) { const el = elements[i]; const elName = el.nodeName.toLowerCase(); if (!allowlistKeys.includes(elName)) { el.remove(); continue; } const attributeList = [].concat(...el.attributes); const allowedAttributes = [].concat(allowList['*'] || [], allowList[elName] || []); attributeList.forEach(attr => { if (!allowedAttribute(attr, allowedAttributes)) { el.removeAttribute(attr.nodeName); } }); } return createdDocument.body.innerHTML; } /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$4 = 'tooltip'; const DATA_KEY$4 = 'bs.tooltip'; const EVENT_KEY$4 = `.${DATA_KEY$4}`; const CLASS_PREFIX$1 = 'bs-tooltip'; const BSCLS_PREFIX_REGEX$1 = new RegExp(`(^|\\s)${CLASS_PREFIX$1}\\S+`, 'g'); const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); const DefaultType$3 = { animation: 'boolean', template: 'string', title: '(string|element|function)', trigger: 'string', delay: '(number|object)', html: 'boolean', selector: '(string|boolean)', placement: '(string|function)', offset: '(array|string|function)', container: '(string|element|boolean)', fallbackPlacements: 'array', boundary: '(string|element)', customClass: '(string|function)', sanitize: 'boolean', sanitizeFn: '(null|function)', allowList: 'object', popperConfig: '(null|object|function)' }; const AttachmentMap = { AUTO: 'auto', TOP: 'top', RIGHT: isRTL() ? 'left' : 'right', BOTTOM: 'bottom', LEFT: isRTL() ? 'right' : 'left' }; const Default$3 = { animation: true, template: '
- 感谢赞助鼠:
'; foreach ($this->appreciates($count) as $appreciate) { if (isset($appreciate->site) && isset($appreciate->site_url)){ $html .= sprintf('- %s: (%s)
', $appreciate->people, $appreciate->site_url, $appreciate->site); } else { $html .= sprintf('- %s
', $appreciate->people); } } $html .= '' + '' + '' + '', trigger: 'hover focus', title: '', delay: 0, html: false, selector: false, placement: 'top', offset: [0, 0], container: false, fallbackPlacements: ['top', 'right', 'bottom', 'left'], boundary: 'clippingParents', customClass: '', sanitize: true, sanitizeFn: null, allowList: DefaultAllowlist, popperConfig: null }; const Event$2 = { HIDE: `hide${EVENT_KEY$4}`, HIDDEN: `hidden${EVENT_KEY$4}`, SHOW: `show${EVENT_KEY$4}`, SHOWN: `shown${EVENT_KEY$4}`, INSERTED: `inserted${EVENT_KEY$4}`, CLICK: `click${EVENT_KEY$4}`, FOCUSIN: `focusin${EVENT_KEY$4}`, FOCUSOUT: `focusout${EVENT_KEY$4}`, MOUSEENTER: `mouseenter${EVENT_KEY$4}`, MOUSELEAVE: `mouseleave${EVENT_KEY$4}` }; const CLASS_NAME_FADE$3 = 'fade'; const CLASS_NAME_MODAL = 'modal'; const CLASS_NAME_SHOW$3 = 'show'; const HOVER_STATE_SHOW = 'show'; const HOVER_STATE_OUT = 'out'; const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; const TRIGGER_HOVER = 'hover'; const TRIGGER_FOCUS = 'focus'; const TRIGGER_CLICK = 'click'; const TRIGGER_MANUAL = 'manual'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Tooltip extends BaseComponent { constructor(element, config) { if (typeof Popper__namespace === 'undefined') { throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)'); } super(element); // private this._isEnabled = true; this._timeout = 0; this._hoverState = ''; this._activeTrigger = {}; this._popper = null; // Protected this._config = this._getConfig(config); this.tip = null; this._setListeners(); } // Getters static get Default() { return Default$3; } static get NAME() { return NAME$4; } static get Event() { return Event$2; } static get DefaultType() { return DefaultType$3; } // Public enable() { this._isEnabled = true; } disable() { this._isEnabled = false; } toggleEnabled() { this._isEnabled = !this._isEnabled; } toggle(event) { if (!this._isEnabled) { return; } if (event) { const context = this._initializeOnDelegatedTarget(event); context._activeTrigger.click = !context._activeTrigger.click; if (context._isWithActiveTrigger()) { context._enter(null, context); } else { context._leave(null, context); } } else { if (this.getTipElement().classList.contains(CLASS_NAME_SHOW$3)) { this._leave(null, this); return; } this._enter(null, this); } } dispose() { clearTimeout(this._timeout); EventHandler.off(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler); if (this.tip) { this.tip.remove(); } if (this._popper) { this._popper.destroy(); } super.dispose(); } show() { if (this._element.style.display === 'none') { throw new Error('Please use show on visible elements'); } if (!(this.isWithContent() && this._isEnabled)) { return; } const showEvent = EventHandler.trigger(this._element, this.constructor.Event.SHOW); const shadowRoot = findShadowRoot(this._element); const isInTheDom = shadowRoot === null ? this._element.ownerDocument.documentElement.contains(this._element) : shadowRoot.contains(this._element); if (showEvent.defaultPrevented || !isInTheDom) { return; } const tip = this.getTipElement(); const tipId = getUID(this.constructor.NAME); tip.setAttribute('id', tipId); this._element.setAttribute('aria-describedby', tipId); this.setContent(); if (this._config.animation) { tip.classList.add(CLASS_NAME_FADE$3); } const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement; const attachment = this._getAttachment(placement); this._addAttachmentClass(attachment); const { container } = this._config; Data.set(tip, this.constructor.DATA_KEY, this); if (!this._element.ownerDocument.documentElement.contains(this.tip)) { container.appendChild(tip); EventHandler.trigger(this._element, this.constructor.Event.INSERTED); } if (this._popper) { this._popper.update(); } else { this._popper = Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment)); } tip.classList.add(CLASS_NAME_SHOW$3); const customClass = typeof this._config.customClass === 'function' ? this._config.customClass() : this._config.customClass; if (customClass) { tip.classList.add(...customClass.split(' ')); } // If this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement) { [].concat(...document.body.children).forEach(element => { EventHandler.on(element, 'mouseover', noop); }); } const complete = () => { const prevHoverState = this._hoverState; this._hoverState = null; EventHandler.trigger(this._element, this.constructor.Event.SHOWN); if (prevHoverState === HOVER_STATE_OUT) { this._leave(null, this); } }; const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE$3); this._queueCallback(complete, this.tip, isAnimated); } hide() { if (!this._popper) { return; } const tip = this.getTipElement(); const complete = () => { if (this._isWithActiveTrigger()) { return; } if (this._hoverState !== HOVER_STATE_SHOW) { tip.remove(); } this._cleanTipClass(); this._element.removeAttribute('aria-describedby'); EventHandler.trigger(this._element, this.constructor.Event.HIDDEN); if (this._popper) { this._popper.destroy(); this._popper = null; } }; const hideEvent = EventHandler.trigger(this._element, this.constructor.Event.HIDE); if (hideEvent.defaultPrevented) { return; } tip.classList.remove(CLASS_NAME_SHOW$3); // If this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { [].concat(...document.body.children).forEach(element => EventHandler.off(element, 'mouseover', noop)); } this._activeTrigger[TRIGGER_CLICK] = false; this._activeTrigger[TRIGGER_FOCUS] = false; this._activeTrigger[TRIGGER_HOVER] = false; const isAnimated = this.tip.classList.contains(CLASS_NAME_FADE$3); this._queueCallback(complete, this.tip, isAnimated); this._hoverState = ''; } update() { if (this._popper !== null) { this._popper.update(); } } // Protected isWithContent() { return Boolean(this.getTitle()); } getTipElement() { if (this.tip) { return this.tip; } const element = document.createElement('div'); element.innerHTML = this._config.template; this.tip = element.children[0]; return this.tip; } setContent() { const tip = this.getTipElement(); this.setElementContent(SelectorEngine.findOne(SELECTOR_TOOLTIP_INNER, tip), this.getTitle()); tip.classList.remove(CLASS_NAME_FADE$3, CLASS_NAME_SHOW$3); } setElementContent(element, content) { if (element === null) { return; } if (isElement(content)) { content = getElement(content); // content is a DOM node or a jQuery if (this._config.html) { if (content.parentNode !== element) { element.innerHTML = ''; element.appendChild(content); } } else { element.textContent = content.textContent; } return; } if (this._config.html) { if (this._config.sanitize) { content = sanitizeHtml(content, this._config.allowList, this._config.sanitizeFn); } element.innerHTML = content; } else { element.textContent = content; } } getTitle() { let title = this._element.getAttribute('data-bs-original-title'); if (!title) { title = typeof this._config.title === 'function' ? this._config.title.call(this._element) : this._config.title; } return title; } updateAttachment(attachment) { if (attachment === 'right') { return 'end'; } if (attachment === 'left') { return 'start'; } return attachment; } // Private _initializeOnDelegatedTarget(event, context) { const dataKey = this.constructor.DATA_KEY; context = context || Data.get(event.delegateTarget, dataKey); if (!context) { context = new this.constructor(event.delegateTarget, this._getDelegateConfig()); Data.set(event.delegateTarget, dataKey, context); } return context; } _getOffset() { const { offset } = this._config; if (typeof offset === 'string') { return offset.split(',').map(val => Number.parseInt(val, 10)); } if (typeof offset === 'function') { return popperData => offset(popperData, this._element); } return offset; } _getPopperConfig(attachment) { const defaultBsPopperConfig = { placement: attachment, modifiers: [{ name: 'flip', options: { fallbackPlacements: this._config.fallbackPlacements } }, { name: 'offset', options: { offset: this._getOffset() } }, { name: 'preventOverflow', options: { boundary: this._config.boundary } }, { name: 'arrow', options: { element: `.${this.constructor.NAME}-arrow` } }, { name: 'onChange', enabled: true, phase: 'afterWrite', fn: data => this._handlePopperPlacementChange(data) }], onFirstUpdate: data => { if (data.options.placement !== data.placement) { this._handlePopperPlacementChange(data); } } }; return { ...defaultBsPopperConfig, ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) }; } _addAttachmentClass(attachment) { this.getTipElement().classList.add(`${CLASS_PREFIX$1}-${this.updateAttachment(attachment)}`); } _getAttachment(placement) { return AttachmentMap[placement.toUpperCase()]; } _setListeners() { const triggers = this._config.trigger.split(' '); triggers.forEach(trigger => { if (trigger === 'click') { EventHandler.on(this._element, this.constructor.Event.CLICK, this._config.selector, event => this.toggle(event)); } else if (trigger !== TRIGGER_MANUAL) { const eventIn = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSEENTER : this.constructor.Event.FOCUSIN; const eventOut = trigger === TRIGGER_HOVER ? this.constructor.Event.MOUSELEAVE : this.constructor.Event.FOCUSOUT; EventHandler.on(this._element, eventIn, this._config.selector, event => this._enter(event)); EventHandler.on(this._element, eventOut, this._config.selector, event => this._leave(event)); } }); this._hideModalHandler = () => { if (this._element) { this.hide(); } }; EventHandler.on(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler); if (this._config.selector) { this._config = { ...this._config, trigger: 'manual', selector: '' }; } else { this._fixTitle(); } } _fixTitle() { const title = this._element.getAttribute('title'); const originalTitleType = typeof this._element.getAttribute('data-bs-original-title'); if (title || originalTitleType !== 'string') { this._element.setAttribute('data-bs-original-title', title || ''); if (title && !this._element.getAttribute('aria-label') && !this._element.textContent) { this._element.setAttribute('aria-label', title); } this._element.setAttribute('title', ''); } } _enter(event, context) { context = this._initializeOnDelegatedTarget(event, context); if (event) { context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; } if (context.getTipElement().classList.contains(CLASS_NAME_SHOW$3) || context._hoverState === HOVER_STATE_SHOW) { context._hoverState = HOVER_STATE_SHOW; return; } clearTimeout(context._timeout); context._hoverState = HOVER_STATE_SHOW; if (!context._config.delay || !context._config.delay.show) { context.show(); return; } context._timeout = setTimeout(() => { if (context._hoverState === HOVER_STATE_SHOW) { context.show(); } }, context._config.delay.show); } _leave(event, context) { context = this._initializeOnDelegatedTarget(event, context); if (event) { context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget); } if (context._isWithActiveTrigger()) { return; } clearTimeout(context._timeout); context._hoverState = HOVER_STATE_OUT; if (!context._config.delay || !context._config.delay.hide) { context.hide(); return; } context._timeout = setTimeout(() => { if (context._hoverState === HOVER_STATE_OUT) { context.hide(); } }, context._config.delay.hide); } _isWithActiveTrigger() { for (const trigger in this._activeTrigger) { if (this._activeTrigger[trigger]) { return true; } } return false; } _getConfig(config) { const dataAttributes = Manipulator.getDataAttributes(this._element); Object.keys(dataAttributes).forEach(dataAttr => { if (DISALLOWED_ATTRIBUTES.has(dataAttr)) { delete dataAttributes[dataAttr]; } }); config = { ...this.constructor.Default, ...dataAttributes, ...(typeof config === 'object' && config ? config : {}) }; config.container = config.container === false ? document.body : getElement(config.container); if (typeof config.delay === 'number') { config.delay = { show: config.delay, hide: config.delay }; } if (typeof config.title === 'number') { config.title = config.title.toString(); } if (typeof config.content === 'number') { config.content = config.content.toString(); } typeCheckConfig(NAME$4, config, this.constructor.DefaultType); if (config.sanitize) { config.template = sanitizeHtml(config.template, config.allowList, config.sanitizeFn); } return config; } _getDelegateConfig() { const config = {}; if (this._config) { for (const key in this._config) { if (this.constructor.Default[key] !== this._config[key]) { config[key] = this._config[key]; } } } return config; } _cleanTipClass() { const tip = this.getTipElement(); const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX$1); if (tabClass !== null && tabClass.length > 0) { tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass)); } } _handlePopperPlacementChange(popperData) { const { state } = popperData; if (!state) { return; } this.tip = state.elements.popper; this._cleanTipClass(); this._addAttachmentClass(this._getAttachment(state.placement)); } // Static static jQueryInterface(config) { return this.each(function () { const data = Tooltip.getOrCreateInstance(this, config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } }); } } /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Tooltip to jQuery only if jQuery is present */ defineJQueryPlugin(Tooltip); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$3 = 'popover'; const DATA_KEY$3 = 'bs.popover'; const EVENT_KEY$3 = `.${DATA_KEY$3}`; const CLASS_PREFIX = 'bs-popover'; const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\s)${CLASS_PREFIX}\\S+`, 'g'); const Default$2 = { ...Tooltip.Default, placement: 'right', offset: [0, 8], trigger: 'click', content: '', template: '' + '' + '' + '' + '' }; const DefaultType$2 = { ...Tooltip.DefaultType, content: '(string|element|function)' }; const Event$1 = { HIDE: `hide${EVENT_KEY$3}`, HIDDEN: `hidden${EVENT_KEY$3}`, SHOW: `show${EVENT_KEY$3}`, SHOWN: `shown${EVENT_KEY$3}`, INSERTED: `inserted${EVENT_KEY$3}`, CLICK: `click${EVENT_KEY$3}`, FOCUSIN: `focusin${EVENT_KEY$3}`, FOCUSOUT: `focusout${EVENT_KEY$3}`, MOUSEENTER: `mouseenter${EVENT_KEY$3}`, MOUSELEAVE: `mouseleave${EVENT_KEY$3}` }; const CLASS_NAME_FADE$2 = 'fade'; const CLASS_NAME_SHOW$2 = 'show'; const SELECTOR_TITLE = '.popover-header'; const SELECTOR_CONTENT = '.popover-body'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class Popover extends Tooltip { // Getters static get Default() { return Default$2; } static get NAME() { return NAME$3; } static get Event() { return Event$1; } static get DefaultType() { return DefaultType$2; } // Overrides isWithContent() { return this.getTitle() || this._getContent(); } getTipElement() { if (this.tip) { return this.tip; } this.tip = super.getTipElement(); if (!this.getTitle()) { SelectorEngine.findOne(SELECTOR_TITLE, this.tip).remove(); } if (!this._getContent()) { SelectorEngine.findOne(SELECTOR_CONTENT, this.tip).remove(); } return this.tip; } setContent() { const tip = this.getTipElement(); // we use append for html objects to maintain js events this.setElementContent(SelectorEngine.findOne(SELECTOR_TITLE, tip), this.getTitle()); let content = this._getContent(); if (typeof content === 'function') { content = content.call(this._element); } this.setElementContent(SelectorEngine.findOne(SELECTOR_CONTENT, tip), content); tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2); } // Private _addAttachmentClass(attachment) { this.getTipElement().classList.add(`${CLASS_PREFIX}-${this.updateAttachment(attachment)}`); } _getContent() { return this._element.getAttribute('data-bs-content') || this._config.content; } _cleanTipClass() { const tip = this.getTipElement(); const tabClass = tip.getAttribute('class').match(BSCLS_PREFIX_REGEX); if (tabClass !== null && tabClass.length > 0) { tabClass.map(token => token.trim()).forEach(tClass => tip.classList.remove(tClass)); } } // Static static jQueryInterface(config) { return this.each(function () { const data = Popover.getOrCreateInstance(this, config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } }); } } /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ * add .Popover to jQuery only if jQuery is present */ defineJQueryPlugin(Popover); /** * -------------------------------------------------------------------------- * Bootstrap (v5.0.2): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * ------------------------------------------------------------------------ * Constants * ------------------------------------------------------------------------ */ const NAME$2 = 'scrollspy'; const DATA_KEY$2 = 'bs.scrollspy'; const EVENT_KEY$2 = `.${DATA_KEY$2}`; const DATA_API_KEY$1 = '.data-api'; const Default$1 = { offset: 10, method: 'auto', target: '' }; const DefaultType$1 = { offset: 'number', method: 'string', target: '(string|element)' }; const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`; const EVENT_SCROLL = `scroll${EVENT_KEY$2}`; const EVENT_LOAD_DATA_API = `load${EVENT_KEY$2}${DATA_API_KEY$1}`; const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; const CLASS_NAME_ACTIVE$1 = 'active'; const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'; const SELECTOR_NAV_LIST_GROUP$1 = '.nav, .list-group'; const SELECTOR_NAV_LINKS = '.nav-link'; const SELECTOR_NAV_ITEMS = '.nav-item'; const SELECTOR_LIST_ITEMS = '.list-group-item'; const SELECTOR_DROPDOWN$1 = '.dropdown'; const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle'; const METHOD_OFFSET = 'offset'; const METHOD_POSITION = 'position'; /** * ------------------------------------------------------------------------ * Class Definition * ------------------------------------------------------------------------ */ class ScrollSpy extends BaseComponent { constructor(element, config) { super(element); this._scrollElement = this._element.tagName === 'BODY' ? window : this._element; this._config = this._getConfig(config); this._selector = `${this._config.target} ${SELECTOR_NAV_LINKS}, ${this._config.target} ${SELECTOR_LIST_ITEMS}, ${this._config.target} .${CLASS_NAME_DROPDOWN_ITEM}`; this._offsets = []; this._targets = []; this._activeTarget = null; this._scrollHeight = 0; EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process()); this.refresh(); this._process(); } // Getters static get Default() { return Default$1; } static get NAME() { return NAME$2; } // Public refresh() { const autoMethod = this._scrollElement === this._scrollElement.window ? METHOD_OFFSET : METHOD_POSITION; const offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; const offsetBase = offsetMethod === METHOD_POSITION ? this._getScrollTop() : 0; this._offsets = []; this._targets = []; this._scrollHeight = this._getScrollHeight(); const targets = SelectorEngine.find(this._selector); targets.map(element => { const targetSelector = getSelectorFromElement(element); const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null; if (target) { const targetBCR = target.getBoundingClientRect(); if (targetBCR.width || targetBCR.height) { return [Manipulator[offsetMethod](target).top + offsetBase, targetSelector]; } } return null; }).filter(item => item).sort((a, b) => a[0] - b[0]).forEach(item => { this._offsets.push(item[0]); this._targets.push(item[1]); }); } dispose() { EventHandler.off(this._scrollElement, EVENT_KEY$2); super.dispose(); } // Private _getConfig(config) { config = { ...Default$1, ...Manipulator.getDataAttributes(this._element), ...(typeof config === 'object' && config ? config : {}) }; if (typeof config.target !== 'string' && isElement(config.target)) { let { id } = config.target; if (!id) { id = getUID(NAME$2); config.target.id = id; } config.target = `#${id}`; } typeCheckConfig(NAME$2, config, DefaultType$1); return config; } _getScrollTop() { return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; } _getScrollHeight() { return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); } _getOffsetHeight() { return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; } _process() { const scrollTop = this._getScrollTop() + this._config.offset; const scrollHeight = this._getScrollHeight(); const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); if (this._scrollHeight !== scrollHeight) { this.refresh(); } if (scrollTop >= maxScroll) { const target = this._targets[this._targets.length - 1]; if (this._activeTarget !== target) { this._activate(target); } return; } if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { this._activeTarget = null; this._clear(); return; } for (let i = this._offsets.length; i--;) { const isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); if (isActiveTarget) { this._activate(this._targets[i]); } } } _activate(target) { this._activeTarget = target; this._clear(); const queries = this._selector.split(',').map(selector => `${selector}[data-bs-target="${target}"],${selector}[href="${target}"]`); const link = SelectorEngine.findOne(queries.join(',')); if (link.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, link.closest(SELECTOR_DROPDOWN$1)).classList.add(CLASS_NAME_ACTIVE$1); link.classList.add(CLASS_NAME_ACTIVE$1); } else { // Set triggered link as active link.classList.add(CLASS_NAME_ACTIVE$1); SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP$1).forEach(listGroup => { // Set triggered links parents as active // With bothand