diff --git a/db/app_uoj233.sql b/db/app_uoj233.sql index 397ad22..aa59101 100644 --- a/db/app_uoj233.sql +++ b/db/app_uoj233.sql @@ -816,6 +816,10 @@ CREATE TABLE `user_info` ( `last_login` timestamp NOT NULL DEFAULT 0, `last_visited` timestamp NOT NULL DEFAULT 0, `images_size_limit` int(11) UNSIGNED NOT NULL DEFAULT 104857600, /* 100 MiB */ + `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `avatar_source` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'gravatar', PRIMARY KEY (`username`), KEY `ac_num` (`ac_num`,`username`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; diff --git a/web/app/controllers/faq.php b/web/app/controllers/faq.php index fdac599..9647fce 100644 --- a/web/app/controllers/faq.php +++ b/web/app/controllers/faq.php @@ -78,6 +78,9 @@

快使用 Gravatar 吧!Gravatar 地址:https://cn.gravatar.com。进去后注册个帐号然后与邮箱绑定并上传头像,就 OK 啦!

+

+ 上不去 Gravatar?没关系,我们现在也支持 QQ 头像了!你只需要前往 “更改个人信息” 页面填写自己的 QQ 号,并将 “头像来源” 选为 “QQ” 就可以让你的 QQ 头像显示在 S2OJ 上啦! +

递归 107 层怎么没爆栈啊

diff --git a/web/app/controllers/user_info.php b/web/app/controllers/user_info.php index 6744dee..688c779 100644 --- a/web/app/controllers/user_info.php +++ b/web/app/controllers/user_info.php @@ -1,4 +1,7 @@ - + - - $user, 'myUser' => $myUser)) ?> - - -

-
-
-
-
- <?= $user['username'] ?> Avatar -
-
-

-
-
-

-

-
-
-

-

-
-
-

-
purify(HTML::parsedown()->line($user['motto'])) ?>
-
- - -
-

register time

-

-
-
-

remote_addr

-

-
-
-

http_x_forwarded_for

-

-
- -
-
-
- - - - - - - - - - 查看 的所有赛后总结 - -
-
-
- -

-
- -
-
- -

- -
-
-
-
- + $user, 'myUser' => $myUser)) ?> diff --git a/web/app/controllers/user_info_edit.php b/web/app/controllers/user_info_edit.php index 853381c..aed14b2 100644 --- a/web/app/controllers/user_info_edit.php +++ b/web/app/controllers/user_info_edit.php @@ -1,4 +1,8 @@ [ + 'name' => ' 个人资料', + 'url' => "/user/{$user['username']}/edit/profile", + ], + 'password' => [ + 'name' => ' 修改密码', + 'url' => "/user/{$user['username']}/edit/password", + ], + 'privilege' => [ + 'name' => ' 特权', + 'url' => "/user/{$user['username']}/edit/privilege", + ] + ]; + + if (!isset($tabs_info[$cur_tab])) { + become404Page(); + } - $email = $_POST['email']; - if (!validateEmail($email)) { - return "失败:无效电子邮箱。"; - } - $esc_email = DB::escape($email); - DB::update("update user_info set email = '$esc_email' where username = '{$user['username']}'"); + if ($cur_tab == 'profile') { + $update_profile_form = new UOJForm('update_profile'); + $username = UOJLocale::get('username'); + $avatar = UOJLocale::get('avatar'); + $update_profile_form->appendHTML(<< + + +
用户名不能被修改。
+ +EOD); + $update_profile_form->addVCheckboxes('avatar_source', [ + 'gravatar' => 'Gravatar', + 'qq' => 'QQ', + ], UOJLocale::get('user::avatar source'), $user['avatar_source']); + $change_avatar_help = UOJLocale::get('change avatar help'); + $update_profile_form->appendHTML(<< + $change_avatar_help + +EOD); + $update_profile_form->addVInput('email', 'email', UOJLocale::get('email'), $user['email'], + function($email, &$vdata) { + if (!validateEmail($email)) { + return 'Email 格式不合法。'; + } - if ($_POST['Qtag']) { - $qq = $_POST['qq']; - if (!validateQQ($qq)) { - return "失败:无效QQ。"; - } - $esc_qq = DB::escape($qq); - DB::update("update user_info set qq = '$esc_qq' where username = '{$user['username']}'"); + $vdata['email'] = $email; + + return ''; + }, null); + $update_profile_form->addVInput('qq', 'text', UOJLocale::get('QQ'), $user['qq'] == 0 ? '' : $user['qq'], + function($qq, &$vdata) { + if ($qq && !validateQQ($qq)) { + return 'QQ 格式不合法。'; + } + + $vdata['qq'] = $qq; + + return ''; + }, null); + $update_profile_form->addVInput('github', 'text', 'GitHub', $user['github'], + function($github, &$vdata) { + if ($github && !validateGitHubUsername($github)) { + return 'GitHub 用户名不合法。'; + } + + $vdata['github'] = $github; + + return ''; + }, null); + if (isSuperUser($myUser)) { + $update_profile_form->addVInput('school', 'text', UOJLocale::get('school'), $user['school'], + function($school, &$vdata) { + $vdata['school'] = $school; + + return ''; + }, null); } else { - DB::update("update user_info set QQ = NULL where username = '{$user['username']}'"); + $school = UOJLocale::get('school'); + $update_profile_form->appendHTML(<< + + +
只有管理员才能修改用户所属学校。
+ +EOD); } - if ($_POST['sex'] == "U" || $_POST['sex'] == 'M' || $_POST['sex'] == 'F') { - $sex = $_POST['sex']; - $esc_sex = DB::escape($sex); - DB::update("update user_info set sex = '$esc_sex' where username = '{$user['username']}'"); - } - - if (validateMotto($_POST['motto'])) { - $esc_motto = DB::escape($_POST['motto']); - DB::update("update user_info set motto = '$esc_motto' where username = '{$user['username']}'"); - } - - return "ok"; + $update_profile_form->addVCheckboxes('sex', [ + 'U' => UOJLocale::get('refuse to answer'), + 'M' => UOJLocale::get('male'), + 'F' => UOJLocale::get('female'), + ], UOJLocale::get('sex'), $user['sex']); + $update_profile_form->addVInput('motto', 'text', UOJLocale::get('motto'), $user['motto'], + function($motto, &$vdata) { + if (!validateMotto($motto)) { + return '格言格式不合法'; + } + + $vdata['motto'] = $motto; + + return ''; + }, null); + $update_profile_form->addVInput('codeforces_handle', 'text', UOJLocale::get('codeforces handle'), $user['codeforces_handle'], + function($codeforces_handle, &$vdata) { + if ($codeforces_handle && !validateUsername($codeforces_handle)) { + return 'Codeforces 用户名格式不合法。'; + } + + $vdata['codeforces_handle'] = $codeforces_handle; + + return ''; + }, null); + $update_profile_form->addVInput('website', 'text', UOJLocale::get('user::website'), $user['website'], + function($url, &$vdata) { + if ($url && !validateURL($url)) { + return '链接格式不合法。'; + } + + $vdata['website'] = $url; + + return ''; + }, null); + $update_profile_form->handle = function(&$vdata) use ($user, $myUser) { + $esc_email = DB::escape($vdata['email']); + $esc_qq = DB::escape($vdata['qq']); + $esc_github = DB::escape($vdata['github']); + $esc_sex = DB::escape($_POST['sex']); + $esc_motto = DB::escape($vdata['motto']); + $esc_codeforces_handle = DB::escape($vdata['codeforces_handle']); + $esc_website = DB::escape($vdata['website']); + $esc_avatar_source = DB::escape($_POST['avatar_source']); + + if (isSuperUser($myUser)) { + $esc_school = DB::escape($vdata['school']); + + DB::update("UPDATE user_info SET school = '$esc_school' WHERE username = '{$user['username']}'"); + } + + DB::update("UPDATE user_info SET email = '$esc_email', qq = '$esc_qq', sex = '$esc_sex', motto = '$esc_motto', codeforces_handle = '$esc_codeforces_handle', github = '$esc_github', website = '$esc_website', avatar_source = '$esc_avatar_source' WHERE username = '{$user['username']}'"); + + header('Content-Type: application/json'); + die(json_encode(['status' => 'success'])); + }; + $update_profile_form->submit_button_config['margin_class'] = 'mt-3'; + $update_profile_form->submit_button_config['text'] = '更新'; + $update_profile_form->setAjaxSubmit(<<runAtServer(); + } elseif ($cur_tab == 'password') { + if (isset($_POST['submit-change_password']) && $_POST['submit-change_password'] == 'change_password') { + header('Content-Type: application/json'); + + $old_password = $_POST['current_password']; + $new_password = $_POST['new_password']; + + if (!validatePassword($old_password) || !checkPassword($user, $old_password)) { + die(json_encode(['status' => 'error', 'message' => '旧密码错误'])); + } + + if (!validatePassword($new_password)) { + die(json_encode(['status' => 'error', 'message' => '新密码不合法'])); + } + + if ($old_password == $new_password) { + die(json_encode(['status' => 'error', 'message' => '新密码不能与旧密码相同'])); + } + + $password = getPasswordToStore($new_password, $user['username']); + DB::update("UPDATE `user_info` SET `password` = '$password' where `username` = '{$user['username']}'"); + die(json_encode(['status' => 'success', 'message' => '密码修改成功'])); + } + } elseif ($cur_tab == 'privilege') { + if (isset($_POST['submit-privilege']) && $_POST['submit-privilege'] == 'privilege' && isSuperUser($myUser)) { + header('Content-Type: application/json'); + + $user['usertype'] = 'student'; + + if ($_POST['user_type'] == 'teacher') { + removeUserType($user, 'student'); + addUserType($user, 'teacher'); + } else { + addUserType($user, 'student'); + } + + if ($_POST['problem_uploader'] == 'yes') { + addUserType($user, 'problem_uploader'); + } + + if ($_POST['problem_manager'] == 'yes') { + addUserType($user, 'problem_manager'); + } + + if ($_POST['contest_judger'] == 'yes') { + addUserType($user, 'contest_judger'); + } + + if ($_POST['contest_only'] == 'yes') { + addUserType($user, 'contest_only'); + } + + DB::update("UPDATE `user_info` SET `usertype` = '{$user['usertype']}' where `username` = '{$user['username']}'"); + + die(json_encode(['status' => 'success', 'message' => '权限修改成功'])); + } } + + $pageTitle = $user['username'] == $myUser['username'] + ? UOJLocale::get('modify my profile') + : UOJLocale::get('modify his profile', $user['username']) ?> - - - - -

您正在使用管理特权修改 的个人信息。

+ + + +

+ +

+ +
+ +
+ +
+ $tab): ?> + + + + +
+ +"> + 返回 + + + + -
- -

-
- -
- - -
-
- -

-
- -
- - - -
-
-
- -
- - -
-
-
- -
- - -
-
-
- -
- -
-
-
- -
- - 格言支持 Markdown 语法。 -
-
-
-
-

-
-
-
-
- -
-
-
- + + +
+
+ +
+ +
+ +
+ +
+ +
+ > + +
+
+ > + +
+
+ +
+ > + +
+ +
+ > + +
+ +
+ > + +
+ +
+ > + +
+
+ + +
+ +
+ + + +
+
+ + +
+
+ diff --git a/web/app/libs/uoj-form-lib.php b/web/app/libs/uoj-form-lib.php index b44bb54..897111a 100644 --- a/web/app/libs/uoj-form-lib.php +++ b/web/app/libs/uoj-form-lib.php @@ -159,7 +159,7 @@ EOD; public function addVSelect($name, $options, $label_text, $default_value) { $default_value = htmlspecialchars($default_value); $html = << +
'; } public static function div_vinput($name, $type, $label_text, $default_value) { - return '
' - . '' + return '
' + . '' . '' - . '' + . '' . '
'; } public static function div_vtextarea($name, $label_text, $default_value) { - return '
' + return '
' . '' . '' . '' diff --git a/web/app/models/UOJLocale.php b/web/app/models/UOJLocale.php index 4c5509f..a986ef3 100644 --- a/web/app/models/UOJLocale.php +++ b/web/app/models/UOJLocale.php @@ -2,7 +2,7 @@ class UOJLocale { public static $supported_locales = array('zh-cn', 'en'); - public static $supported_modules = array('basic', 'contests', 'problems', 'time'); + public static $supported_modules = array('basic', 'contests', 'problems', 'time', 'user'); public static $data = array(); public static $required = array(); diff --git a/web/app/models/Upgrader.php b/web/app/models/Upgrader.php index 05d83f7..3a98771 100644 --- a/web/app/models/Upgrader.php +++ b/web/app/models/Upgrader.php @@ -105,7 +105,7 @@ class Upgrader { public static function upgradeToLatest() { $names = array_filter(scandir(self::upgraderRoot()), function ($name) { - return is_dir(self::upgraderRoot().'/'.$name) && preg_match('/^\d+_[a-zA-Z_]+$/', $name); + return is_dir(self::upgraderRoot().'/'.$name) && preg_match('/^\d+_[0-9a-zA-Z_]+$/', $name); }); natsort($names); diff --git a/web/app/route.php b/web/app/route.php index dd77b1e..f4f2789 100644 --- a/web/app/route.php +++ b/web/app/route.php @@ -72,7 +72,7 @@ Route::group([ Route::any('/reset-password', '/reset_pw.php'); Route::any('/user/{username}', '/user_info.php'); - Route::any('/user/{username}/edit', '/user_info_edit.php'); + Route::any('/user/{username}/edit(?:/{tab})?', '/user_info_edit.php'); Route::any('/user_msg', '/user_msg.php'); Route::any('/user/{username}/system_msg', '/user_system_msg.php'); diff --git a/web/app/upgrade/6_user_info_v2/README.md b/web/app/upgrade/6_user_info_v2/README.md new file mode 100644 index 0000000..e0c36ee --- /dev/null +++ b/web/app/upgrade/6_user_info_v2/README.md @@ -0,0 +1 @@ +ref: https://github.com/renbaoshuo/S2OJ/pull/6 diff --git a/web/app/upgrade/6_user_info_v2/down.sql b/web/app/upgrade/6_user_info_v2/down.sql new file mode 100644 index 0000000..ea11898 --- /dev/null +++ b/web/app/upgrade/6_user_info_v2/down.sql @@ -0,0 +1,4 @@ +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `codeforces_handle`; +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `github`; +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `website`; +ALTER TABLE `user_info` DROP COLUMN IF EXISTS `avatar_source`; diff --git a/web/app/upgrade/6_user_info_v2/up.sql b/web/app/upgrade/6_user_info_v2/up.sql new file mode 100644 index 0000000..830ca6f --- /dev/null +++ b/web/app/upgrade/6_user_info_v2/up.sql @@ -0,0 +1,4 @@ +ALTER TABLE `user_info` ADD COLUMN `codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; +ALTER TABLE `user_info` ADD COLUMN `github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; +ALTER TABLE `user_info` ADD COLUMN `website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT ''; +ALTER TABLE `user_info` ADD COLUMN `avatar_source` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'gravatar'; diff --git a/web/app/views/page-header.php b/web/app/views/page-header.php index dc6e8ca..4fd4300 100644 --- a/web/app/views/page-header.php +++ b/web/app/views/page-header.php @@ -219,12 +219,6 @@ - - - - - - diff --git a/web/app/views/user-info.php b/web/app/views/user-info.php index bc22b8f..546f6dd 100644 --- a/web/app/views/user-info.php +++ b/web/app/views/user-info.php @@ -68,7 +68,7 @@ function fTime($time, $gran = -1) {
- +

@@ -102,35 +102,107 @@ function fTime($time, $gran = -1) {
  • $type): ?> - , - - - - - - - - - - - - - - - + , +
  • +
  • +
  • - + + + +
  • + + +
  • + + + + +
  • + + +
  • +
    Codeforces 
    +
    + + + +
    +
    + +
  • + + +
  • + + + +
  • @@ -139,16 +211,16 @@ function fTime($time, $gran = -1) { - + - + 0): ?> - , + , @@ -182,10 +254,34 @@ function fTime($time, $gran = -1) { - 赛后总结 + -
    + + + +
    +
    +

    + +

    + +
    +
    + + +
    -
    -
    +
    +

    @@ -233,7 +329,7 @@ while ($row = DB::fetch($_result)) { -

    +
    diff --git a/web/css/github_contribution_graph.css b/web/css/github_contribution_graph.css deleted file mode 100644 index f2a43b6..0000000 --- a/web/css/github_contribution_graph.css +++ /dev/null @@ -1,24 +0,0 @@ -.svg-tip { - padding: 10px; - background: rgba(0,0,0,0.8); - color: #bbb; - font-size: 12px; - position: absolute; - z-index: 99999; - text-align: center; - border-radius: 3px; -} - -.svg-tip:after { - -moz-box-sizing: border-box; - box-sizing: border-box; - position: absolute; - left: 50%; - height: 5px; - width: 5px; - bottom: -10px; - margin: 0 0 0 -5px; - content: " "; - border: 5px solid transparent; - border-top-color: rgba(0,0,0,0.8); -} diff --git a/web/js/jquery.github_contribution_graph.js b/web/js/jquery.github_contribution_graph.js deleted file mode 100644 index c6223f9..0000000 --- a/web/js/jquery.github_contribution_graph.js +++ /dev/null @@ -1,308 +0,0 @@ -/** - * Jquery plugin to render like contribution graph on Github. - * - * @see {@link https://github.com/bachvtuan/Github-Contribution-Graph} - * @author bachvtuan@gmail.com - * @license MIT License - * @since 0.1.0 - */ - -//Format string -if (!String.prototype.formatString) { - String.prototype.formatString = function () { - var args = arguments; - return this.replace(/{(\d+)}/g, function (match, number) { - return typeof args[number] != "undefined" ? args[number] : match; - }); - }; -} - -(function ($) { - $.fn.github_graph = function (options) { - //If the number less than 10, add Zero before it - var prettyNumber = function (number) { - return number < 10 - ? "0" + number.toString() - : (number = number.toString()); - }; - - /* - Count the number on each day and store the object - */ - var processListTimeStamp = function (list_timestamp) { - //The result will store into this varriable - obj_timestamp = {}; - for (var i = 0; i < list_timestamp.length; i++) { - var _type = typeof list_timestamp[i]; - var _d = - _type == "number" - ? new Date(list_timestamp[i]) - : new Date(list_timestamp[i].timestamp); - - var display_date = getDisplayDate(_d); - var increase = _type == "number" ? 1 : list_timestamp[i].count; - if (!obj_timestamp[display_date]) { - obj_timestamp[display_date] = increase; - } else { - obj_timestamp[display_date] += increase; - } - } - }; - - var getDisplayDate = function (date_obj) { - var pretty_month = prettyNumber(date_obj.getMonth() + 1); - var pretty_date = prettyNumber(date_obj.getDate()); - return "{0}-{1}-{2}".formatString( - date_obj.getFullYear(), - pretty_month, - pretty_date - ); - }; - - var getCount = function (display_date) { - if (obj_timestamp[display_date]) { - return obj_timestamp[display_date]; - } - return 0; - }; - - var getColor = function (count) { - if (typeof settings.colors[0] == "string") { - return count > settings.colors.length - 1 - ? settings.colors[settings.colors.length - 1] - : settings.colors[count]; - } - - const isLargeNumber = (element) => element.count > count; - i = settings.colors.findIndex(isLargeNumber); - return i == -1 - ? settings.colors[settings.colors.length - 1].color - : settings.colors[i - 1].color; - }; - - var start = function () { - processListTimeStamp(settings.data); - var wrap_chart = _this; - - settings.colors_length = settings.colors.length; - var radius = settings.border.radius; - var hoverColor = settings.border.hover_color; - var clickCallback = settings.click; - - var start_date; - if (settings.start_date == null) { - // if set null, will get from 365 days from now - start_date = new Date(); - start_date.setMonth(start_date.getMonth() - 12); - start_date.setDate(start_date.getDate() + 1); - } else { - // formats: - // - YYYY-MM-DD - // - YYYY/MM/DD - start_date = new Date(settings.start_date); - } - - end_date = new Date(start_date); - end_date.setMonth(end_date.getMonth() + 12); - end_date.setDate(end_date.getDate() - 1); - - var loop_html = ""; - var step = 13; - - var month_position = []; - month_position.push({ month_index: start_date.getMonth(), x: 0 }); - var using_month = start_date.getMonth(); - - var week = 0; - var g_x = week * step; - var item_html = - ''; - - for ( - ; - start_date.getTime() <= end_date.getTime(); - start_date.setDate(start_date.getDate() + 1) - ) { - if (start_date.getDay() == 0) { - var item_html = - ''; - } - - var month_in_day = start_date.getMonth(); - var data_date = getDisplayDate(start_date); - - if (start_date.getDay() == 0 && month_in_day != using_month) { - using_month = month_in_day; - month_position.push({ month_index: using_month, x: g_x }); - } - var count = getCount(data_date); - var color = getColor(count); - - var y = start_date.getDay() * step; - item_html += - ''; - - if (start_date.getDay() == 6) { - item_html += ""; - loop_html += item_html; - - item_html = null; - - week++; - g_x = week * step; - } - } - - if (item_html != null) { - item_html += ""; - loop_html += item_html; - } - - //trick - if (month_position[1].x - month_position[0].x < 40) { - //Fix ugly graph by remove first item - month_position.shift(0); - } - - for (var i = 0; i < month_position.length; i++) { - var item = month_position[i]; - var month_name = settings.month_names[item.month_index]; - loop_html += - '' + - month_name + - ""; - } - - //Add Monday, Wenesday, Friday label - loop_html += - '{0}'.formatString( - settings.h_days[0] - ) + - '{0}'.formatString( - settings.h_days[1] - ) + - '{0}'.formatString( - settings.h_days[2] - ); - - //Fixed size for now with width= 721 and height = 110 - var wire_html = - '' + - '' + - loop_html + - "" + - ""; - - wrap_chart.html(wire_html); - - $(_this) - .find(".day") - .on("click", function () { - if (clickCallback) { - clickCallback( - $(this).attr("data-date"), - parseInt($(this).attr("data-count")) - ); - } - }); - - $(_this) - .find(".day") - .hover( - function () { - $(this).attr( - "style", - "stroke-width: 1; stroke: " + hoverColor - ); - }, - function () { - $(this).attr("style", "stroke-width:0"); - } - ); - - _this.find("rect").on("mouseenter", mouseEnter); - _this.find("rect").on("mouseleave", mouseLeave); - appendTooltip(); - }; - - var mouseLeave = function (evt) { - $(".svg-tip").hide(); - }; - - //handle event mouseenter when enter into rect element - var mouseEnter = function (evt) { - var target_offset = $(evt.target).offset(); - var count = $(evt.target).attr("data-count"); - var date = $(evt.target).attr("data-date"); - - var count_text = count > 1 ? settings.texts[1] : settings.texts[0]; - var text = "{0} {1} on {2}".formatString(count, count_text, date); - - var svg_tip = $(".svg-tip").show(); - svg_tip.html(text); - var svg_width = Math.round(svg_tip.width() / 2 + 5); - var svg_height = svg_tip.height() * 2 + 10; - - svg_tip.css({ top: target_offset.top - svg_height - 5 }); - svg_tip.css({ left: target_offset.left - svg_width }); - }; - //Append tooltip to display when mouse enter the rect element - //Default is display:none - var appendTooltip = function () { - if ($(".svg-tip").length == 0) { - $("body").append( - '' - ); - } - }; - - var settings = $.extend( - { - colors: ["#eeeeee", "#d6e685", "#8cc665", "#44a340", "#44a340"], - border: { - radius: 2, - hover_color: "#999", - }, - click: null, - start_date: null, - //List of name months - month_names: [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - ], - h_days: ["M", "W", "F"], - //Default is empty, it can be overrided - data: [], - }, - options - ); - - var _this = $(this); - - start(); - }; -})(jQuery);