Compare commits

..
82 Commits
Author SHA1 Message Date
Hide_D f2a785f2fc imagePull 기능 추가, 인스톨러 완성 2019-09-23 00:28:15 +09:00
Hide_D 6fafcfae4e 훈사 분리 2019-09-21 23:27:43 +09:00
Hide_D 33e075f669 훈사를 분리 2019-09-21 21:29:20 +09:00
Hide_D e5fc467c4e 버그 수정 2019-09-21 21:04:17 +09:00
Hide_D b7a5de49c6 표기 일부 변경 2019-09-21 18:09:37 +09:00
Hide_D 3f145abd6f 모훈사 기준을 징병 6회로 변경 2019-09-21 17:39:13 +09:00
Hide_D 4612834870 워프 기준, 쌀 삼팜 기준 변경 2019-09-21 14:41:23 +09:00
Hide_D 83c5609fad 징병 버그 수정 2 2019-09-21 11:42:10 +09:00
Hide_D d142056098 징병 안되는 버그 수정 2019-09-21 11:39:51 +09:00
Hide_D 4d8ecf4191 진짜로 삭턴 버그 수정 2019-09-21 02:44:00 +09:00
Hide_D af6c3f466d 삭턴 버그 수정 2019-09-21 02:38:06 +09:00
Hide_D 033a2d8674 삭턴 버그 수정 2019-09-21 02:35:15 +09:00
Hide_D 9079788b2b 삭턴 기준 변경 2019-09-21 02:33:39 +09:00
Hide_D 44ddb2e480 git fetch에도 -q 2019-09-21 02:28:49 +09:00
Hide_D 295ba84071 자동 행동 세부를 툴팁으로 2019-09-21 02:27:05 +09:00
Hide_D 8773250aab 초기 병종이 보병일 때 고정되는 버그 수정 2019-09-21 02:14:25 +09:00
Hide_D c5a4602fe1 옵션 표기 버그 수정 2019-09-21 02:11:54 +09:00
Hide_D 5f4c43baf6 Merge branch 'devel' into autorun 2019-09-21 02:07:26 +09:00
Hide_D 0ef3921e17 update 서버 변경 2019-09-21 02:06:49 +09:00
Hide_D efcf0f772e server checkout 추가2 2019-09-21 01:50:36 +09:00
Hide_D ccabe847bb 루트도 git tree-ish 지정 가능 2019-09-21 01:42:21 +09:00
Hide_D 45ed63ffe3 버그 수정 2019-09-21 01:38:29 +09:00
Hide_D 7bebbe3a16 징병, 모병 추가 2019-09-21 01:09:17 +09:00
Hide_D 53ba1db79f autorun_user 초기 세팅 2019-09-20 02:12:42 +09:00
Hide_D 76c306a122 npc AI를 '사전 턴' 수행 이후에 처리하도록 변경 2019-09-20 00:41:38 +09:00
Hide_D 89c2c163cb 서버 정보에 자동행동 표기 2019-09-20 00:35:13 +09:00
Hide_D 8826061266 autorun_user 인자 세팅 2019-09-20 00:05:40 +09:00
Hide_D e684877c94 리셋 화면에서 '휴식 턴 시 장수 턴' 추가 2019-09-19 02:21:51 +09:00
Hide_D 12c8152901 docker 메시지 수정 2019-09-19 01:16:21 +09:00
Hide_D 8ba20bf4d2 Docker를 이용한 설치 안내 2019-09-15 23:25:11 +09:00
Hide_D 0bc1ad09d1 년도 변경 2019-09-15 23:19:04 +09:00
Hide_D 231c79132a run_daemon 1분 유지 수정 2019-09-15 20:59:35 +09:00
Hide_D 089803c599 cron 수정 2019-09-15 20:53:23 +09:00
Hide_D 4ea373aff6 gitignore change 2019-09-15 20:08:57 +09:00
Hide_D 0d94b8c742 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2019-09-15 19:49:32 +09:00
Hide_D d444f19043 date_default_timezone_set 해제 2019-09-15 19:49:24 +09:00
Hide_D 87a0e73c96 인스톨러 버그 수정 2019-09-15 02:59:38 +09:00
Hide_D b5922095f0 인스톨러 임시 트윅 2019-09-15 02:50:10 +09:00
Hide_D 3fee29e9e9 setup_db에서 global_salt 추가 2019-09-15 00:55:57 +09:00
Hide_D 4e351b3be8 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2019-09-15 00:38:00 +09:00
Hide_D 3432b900df 설치 직후 기본 gitpath 변경 2019-09-15 00:37:46 +09:00
Hide_D fb7c67f317 빙의 안되는 버그 수정, 가입/빙의 시 락 2019-08-18 18:01:11 +09:00
Hide_D 28d5a5c39a 장수 생성시 빠르게 쿼리를 날려 중복 생성하는 것이 불가능하도록 2019-08-18 17:50:38 +09:00
Hide_D e2754511d9 부대탈퇴 시 propergation 처리 실수 수정 2019-08-18 00:46:39 +09:00
Hide_D 71d179de76 서버 시간을 더 정교하게 반영하도록 수정 2019-08-16 23:42:46 +09:00
Hide_D 08523852da 마지막 남은 iframe 안녕!!! 2019-08-16 23:27:28 +09:00
Hide_D 3dd52942d2 부대 명령을 json api로 변경 2019-08-16 22:16:28 +09:00
Hide_D bb24e45028 서버가 오픈되지 않으면 벌점이 늘지 않도록 변경 2019-08-15 19:37:03 +09:00
Hide_D f8c72a6a0a NPC기술연구 관련 마저 고침 2019-08-15 16:10:39 +09:00
Hide_D fa246ff810 단순 건국 상품 롤백 2019-08-15 00:37:49 +09:00
Hide_D 1a1d384a3e 최종 보정 수정 2019-08-14 01:36:41 +09:00
Hide_D 6d85c609fd 동시에 관직이 여러번 뛸때에도 관직 보상 많이 줌 2019-08-14 01:33:50 +09:00
Hide_D e1b8dde60a 보정 롤백 2019-08-14 01:27:37 +09:00
Hide_D e8d32eef4e 작위보상의 수뇌 보정을 낮춤 2019-08-14 01:26:05 +09:00
Hide_D ec0fa686a9 여유를 '절대 시간' 으로 변경 2019-08-14 01:00:10 +09:00
Hide_D 7604273c1a 삭턴에 조금 여유를 줌 2019-08-14 00:58:56 +09:00
Hide_D 00db927ce7 작위 보상 추가 2019-08-14 00:55:45 +09:00
Hide_D 9fea24f0f6 건국 즉시 얻는 템 삭제, 유니크 복권 리팩토링, '고정된 한개'를 주는 유니크 복권 추가 2019-08-14 00:27:36 +09:00
Hide_D c903ce929f 서버 정보 추가 제공 2019-08-13 23:37:46 +09:00
Hide_D d48d9f85b3 가오픈시 별도 표기 추가 2019-08-13 23:24:05 +09:00
Hide_D 5bdf7ba316 가오픈시 삭제는 유저장만 가능하도록 변경 2019-08-13 02:24:58 +09:00
Hide_D 518c74736f 가 오픈기간내 장수 삭제/빙의해제 가능 2019-08-13 02:23:27 +09:00
Hide_D 223d2cf786 서버 가오픈시 대비 넉넉하게 시간 제공 2019-08-13 01:30:41 +09:00
Hide_D cfa2cff34a NPC의 기술 연구 기준을 '기술제한이 아니면'으로 변경 2019-08-13 00:20:07 +09:00
Hide_D 26eacfe795 랜임 버그 핫픽스 2019-07-18 21:21:58 +09:00
Hide_D b1b937ee31 (6턴 제외) 삭턴사시 본닉 공개 2019-07-17 23:32:59 +09:00
Hide_D 122479158c '장수를 따라' 임관하는 기능 추가 2019-07-17 23:06:20 +09:00
Hide_D 0af5e9ec84 외교권자 임명 시 내부적으로 warning뜨는 버그 수정 2019-07-17 21:19:34 +09:00
Hide_D cb5414f789 youtube, vimeo iframe 가능하도록 변경 2019-07-17 21:12:25 +09:00
sars 224cb1b913 server_title id 추가 2019-07-10 19:52:29 -07:00
sars 8bd84cc701 serverCnt 변수로 지정 2019-07-10 19:39:25 -07:00
sars a14dcf8b3e 깃수 출력 2019-07-10 15:27:44 -07:00
Hide_D a1a26bf8fe 훈련,사기템 효과 두배 증가, 철벽서 버그 수정 2019-06-21 10:06:05 +09:00
Hide_D fea229c4ad 사령부 턴 높이 늘림 2019-06-21 09:58:17 +09:00
Hide_D 7040d940ac 왕조 일람 정보 추가 2019-06-21 09:55:40 +09:00
Hide_D a576d72335 메인 페이지 부대 이름 관련 보조정보 추가 2019-06-21 09:51:39 +09:00
Hide_D 5aab373d20 발령, 포상, 몰수에서 보조 데이터 추가 2019-06-21 09:29:33 +09:00
Hide_D 32f8160eb2 시즌 값 추가 2019-06-18 03:32:14 +09:00
Hide_D 701355beb3 시즌 별 검색 기능 추가, 기본 값으로 현재 시즌 표기 2019-06-18 03:30:09 +09:00
Hide_D 28de7c517b UniqueConst와 game_env에 seasonIdx 추가 2019-06-18 03:12:36 +09:00
Hide_D 7365ca7a64 숙련전환 커맨드 추가 2019-06-16 04:42:43 +09:00
Hide_D 2a61813b67 스1 시나리오 업데이트 2019-06-14 23:55:43 +09:00
2300 changed files with 187812 additions and 147360 deletions
-15
View File
@@ -1,15 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"modules": false
}
]
],
"plugins": [
"lodash"
]
}
-54
View File
@@ -1,54 +0,0 @@
module.exports = {
root: true,
parser: "vue-eslint-parser",
"env": {
"browser": true,
"es2021": true,
'vue/setup-compiler-macros': true
},
ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'postcss.config.cjs', 'webpack.config.cjs', '*.js'],
overrides: [{
files: ['*.ts', '*.tsx', "*.vue"],
}],
plugins: [
"@typescript-eslint",
"prettier"
],
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
],
parserOptions: {
"sourceType": "module",
"project": "./tsconfig.json",
"ecmaVersion": 2021,
"parser": "@typescript-eslint/parser",
extraFileExtensions: ['.vue']
},
rules: {
'@typescript-eslint/no-floating-promises': 'error',
'vue/script-setup-uses-vars': 'error',
'vue/max-attributes-per-line': [
'warn',
{
singleline: 4, //prettier와 싸우지 말자
},
],
'vue/v-on-event-hyphenation': 'off', //vue3에선 필요없다고 생각
'vue/attribute-hyphenation': 'off', //vue3에선 필요없다고 생각
},
settings: {
'import/resolver': {
alias: {
map: [
['@', './hwe/ts'],
['@util', './hwe/ts/util'],
['@scss', './hwe/scss'],
]
}
}
},
};
+44 -67
View File
@@ -1,67 +1,44 @@
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
/node_modules
# 체섭 ignore
*.log
logs/*.txt
d_log/*.txt
d_log/*.zip
sess_*
*/logs/*.txt
*/logs/*/*.txt
*/logs/preserved
err.txt
hwe/.htaccess
d_shared
/d_pic
d_pic/*.jpg
d_pic/*.gif
d_pic/*.png
d_pic/*.webp
d_pic/uploaded_image
/dist_js
*/dist_misc/*
*/dist_js/*
*/dist_css/*
/dist_misc/*
/dist_js/*
/dist_css/*
d_setting/*.php
*/d_setting/*.php
*/d_setting/*.json
*/d_setting/templates/*.php
!*.orig.php
**/data/file_cache
**/old/*
test.*
/che
/kwe
/pwe
/nya
/pya
/twe
/hwe/data
/vendor
phpinfo.php
*.sqlite3
ingame/js/*
ingame/css/*
gateway/js/*
gateway/css/*
.vscode/*
# 체섭 ignore
*.log
logs/*.txt
d_log/*.txt
d_log/*.zip
sess_*
*/logs/*.txt
*/logs/*/*.txt
*/logs/preserved
err.txt
che/.htaccess
kwe/.htaccess
pwe/.htaccess
twe/.htaccess
hwe/.htaccess
d_shared
d_pic/*.jpg
d_pic/*.gif
d_pic/*.png
d_pic/uploaded_image
d_setting/*.php
*/d_setting/*.php
*/d_setting/templates/*.php
**/old/*
test.php
/che
/kwe
/pwe
/nya
/pya
/twe
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
-12
View File
@@ -1,12 +0,0 @@
{
"extension": ["ts"],
"spec": "hwe/test-ts/**/*.test.ts",
"require": [
"ts-node/register",
"tsconfig-paths/register"
],
"node-option": [
"experimental-specifier-resolution=node",
"loader=ts-node/esm"
]
}
+21 -115
View File
@@ -2,133 +2,44 @@
/**
* This configuration will be read and overlaid on top of the
* default configuration. Command-line arguments will be applied
* default configuration. Command line arguments will be applied
* after this file is read.
*/
return [
// Supported values: `'5.6'`, `'7.0'`, `'7.1'`, `'7.2'`, `'7.3'`,
// `'7.4'`, `'8.0'`, `'8.1'`, `null`.
// If this is set to `null`,
// Supported values: '7.0', '7.1', '7.2', null.
// If this is set to null,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan.
//
// Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options)
"target_php_version" => '8.1',
"minimum_target_php_version" => '8.1',
'backward_compatibility_checks ' => true,
'minimum_severity' => \Phan\Issue::SEVERITY_NORMAL,
// of the php executable used to execute phan.
"target_php_version" => '7.0',
'backward_compatibility_checks ' => false,
'ignore_undeclared_variables_in_global_scope' => false,
'minimum_severity'=>\Phan\Issue::SEVERITY_LOW,
'file_list' => [
'f_config/config.php',
'hwe/_119_b.php',
'hwe/_119.php',
'hwe/a_bestGeneral.php',
'hwe/_admin1.php',
'hwe/_admin1_submit.php',
'hwe/_admin2.php',
'hwe/_admin2_submit.php',
'hwe/_admin4.php',
'hwe/_admin4_submit.php',
'hwe/_admin5.php',
'hwe/_admin5_submit.php',
'hwe/_admin7.php',
'hwe/_admin8.php',
'hwe/_admin_force_rehall.php',
'hwe/a_emperior_detail.php',
'hwe/a_emperior.php',
'hwe/a_genList.php',
'hwe/a_hallOfFame.php',
'hwe/a_kingdomList.php',
'hwe/a_npcList.php',
'hwe/api.php',
'hwe/a_traffic.php',
'hwe/battle_simulator.php',
'hwe/b_battleCenter.php',
'hwe/b_betting.php',
'hwe/v_chiefCenter.php',
'hwe/b_currentCity.php',
'hwe/v_nationStratFinan.php',
'hwe/b_genList.php',
'hwe/b_myBossInfo.php',
'hwe/b_myCityInfo.php',
'hwe/b_myGenInfo.php',
'hwe/b_myKingdomInfo.php',
'hwe/b_myPage.php',
'hwe/v_processing.php',
'hwe/b_tournament.php',
'hwe/b_troop.php',
'hwe/c_tournament.php',
'hwe/MYDB.php',
'hwe/lib.php',
'hwe/func_auction.php',
'hwe/func_command.php',
'hwe/func_converter.php',
'hwe/func_diplomacy.php',
'hwe/func_gamerule.php',
'hwe/func_history.php',
'hwe/func_legacy.php',
'hwe/func_map.php',
'hwe/func_message.php',
'hwe/func.php',
'hwe/func_npc.php',
'hwe/func_process_chief.php',
'hwe/func_process_personnel.php',
'hwe/func_process_sabotage.php',
'hwe/func_process.php',
'hwe/func_string.php',
'hwe/func_template.php',
'hwe/func_time_event.php',
'hwe/func_tournament.php',
'hwe/index.php',
'hwe/install_db.php',
'hwe/install.php',
'hwe/j_adjust_icon.php',
'hwe/j_autoreset.php',
'hwe/j_basic_info.php',
'hwe/j_board_article_add.php',
'hwe/j_board_comment_add.php',
'hwe/j_board_get_articles.php',
'hwe/j_die_immediately.php',
'hwe/j_diplomacy_destroy_letter.php',
'hwe/j_diplomacy_get_letter.php',
'hwe/j_diplomacy_respond_letter.php',
'hwe/j_diplomacy_rollback_letter.php',
'hwe/j_diplomacy_send_letter.php',
'hwe/j_export_simulator_object.php',
'hwe/j_general_log_old.php',
'hwe/j_general_set_permission.php',
'hwe/j_get_basic_general_list.php',
'hwe/j_get_city_list.php',
'hwe/j_get_select_npc_token.php',
'hwe/j_get_select_pool.php',
'hwe/j_install_db.php',
'hwe/j_install.php',
'hwe/j_load_scenarios.php',
'hwe/j_map.php',
'hwe/j_map_recent.php',
'hwe/j_msg_contact_list.php',
'hwe/j_msg_decide_opt.php',
'hwe/j_msg_delete.php',
'hwe/j_msg_get_old.php',
'hwe/j_msg_get_recent.php',
'hwe/j_msg_submit.php',
'hwe/j_myBossInfo.php',
'hwe/j_raise_event.php',
'hwe/j_select_npc.php',
'hwe/j_select_picked_general.php',
'hwe/j_server_basic_info.php',
'hwe/j_set_my_setting.php',
'hwe/j_set_npc_control.php',
'hwe/j_simulate_battle.php',
'hwe/j_troop.php',
'hwe/j_update_picked_general.php',
'hwe/j_vacation.php',
'hwe/lib.php',
'hwe/process_war.php',
'hwe/proc.php',
'hwe/recent_map.php',
'hwe/select_general_from_pool.php',
'hwe/select_npc.php',
'hwe/t_diplomacy.php',
'hwe/v_board.php',
'hwe/v_inheritPoint.php',
'hwe/v_join.php',
'hwe/v_NPCControl.php',
'hwe/func.php'
],
// A list of directories that should be parsed for class and
@@ -139,9 +50,9 @@ return [
// Thus, both first-party and third-party code being used by
// your application should be included in this list.
'directory_list' => [
'hwe/d_setting',
'hwe/sammo',
'd_setting',
'hwe/d_setting',
'hwe/sammo',
'd_setting',
'src/sammo',
'src/kakao',
'vendor'
@@ -163,11 +74,6 @@ return [
'vendor/'
],
'suppress_issue_types' => [
'PhanUnreferencedUseNormal',
'PhanTypeArraySuspiciousNullable',
],
// A list of plugin files to execute.
// See https://github.com/phan/phan/tree/master/.phan/plugins for even more.
// (Pass these in as relative paths.
@@ -182,4 +88,4 @@ return [
'PregRegexCheckerPlugin',
'PrintfCheckerPlugin',
],
];
];
-5
View File
@@ -1,5 +0,0 @@
{
"tabWidth": 2,
"useTabs": false,
"printWidth": 120
}
+2 -7
View File
@@ -13,7 +13,7 @@
"/nya":true,
"/pya":true,
"/twe":true,
},
"search.exclude": {
"e_lib/*":true,
@@ -24,10 +24,5 @@
"/nya":true,
"/pya":true,
"/twe":true,
},
"cSpell.words": [
"josa",
"sammo"
],
"editor.tabSize": 2
},
}
-23
View File
@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>닫혀 있습니다.</title>
<script>
setTimeout(function(){
window.location.href = '../';
}, 5000);
</script>
<style>
html, body{
background-color:black;
color:yellow;
}
</style>
</head>
<body>
서버가 닫혀있습니다.<br>
잠시 뒤에 입구로 이동합니다.
</body>
</html>
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2022 Hide_D, 62che
Copyright (c) 2019 Hide_D, 62che
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+17 -20
View File
@@ -5,44 +5,41 @@
## 요구사항
* Apache2 또는 nginx
* Apache2인 경우 `mpm_event` 권장
* PHP 8.0 이상
* `php-fpm` 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다.
* mysqli, mysqlnd
* Apache2
* <code>mpm_event</code> 권장
* PHP 7.2 이상
* <code>php-fpm</code> 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다. (기본값: 지원)
* mysqlnd가 지원되어야합니다. (기본값: 지원)
* mysqli
* gd
* mbstring
* NodeJS 14 이상
* 내부의 git을 통해 upgrade 때 `webpack build` 용도로 필요합니다.
* MariaDB 10.2.1 이상
* 현재 MySQL은 지원하지 않습니다.
* `git`
* `curl`
* <code>git</code>
* <code>curl</code>
Linux는 Ubuntu 18.04, 20.04, Windows는 WSL2를 사용한 환경에서 테스트되었습니다.
Linux는 Ubuntu 16.04, 18.04, Windows는 Windows 10에서 XAMPP를 사용한 환경에서 테스트되었습니다.
Docker를 이용한 설치도 제공하고 있습니다.
## Docker를 이용한 설치
https://storage.hided.net/gitea/devsam/docker 를 참고해 주세요.
https://storage.hided.net/gogs/devsam/docker 를 참고해 주세요.
## 수동 설치
본 게임은 <code>git</code>을 이용한 업그레이드 시스템을 구현하였으므로, <code>git</code>이 필요합니다.
또한 웹 서비스 데몬을 운영중인 사용자(일반적으로 <code>www-data</code>)에게 디렉토리 권한이 주어져야합니다.
또한 웹 서비스 데몬을 운영중인 사용자(일반적으로 <code>www-data</code>, <code>apache</code>)에게 디렉토리 권한이 주어져야합니다.
### 다운로드
웹 데몬 user가 <code>www-data</code>인 경우 다음과 같이 입력하여 최신 배포버전과 이미지 파일을 얻을 수 있습니다.
```
sudo -u www-data git clone https://storage.hided.net/gitea/devsam/core.git
sudo -u www-data git clone https://storage.hided.net/gitea/devsam/image.git
sudo -u www-data git clone https://storage.hided.net/gogs/devsam/core.git
git clone https://storage.hided.net/gogs/devsam/image.git
```
> 이미지는 hook/git_hook.php을 통해 동기화되며, 서버 설치 과정에 이미지 갱신 키를 지정하는 것으로 '훼' 서버 업데이트 시 동기화됩니다. 이미지 서버가 게임 서버와 별개여도 동작하나, php와 git을 지원해야합니다.
> 이미지는 git hook을 이용한 업데이트 기능을 제공하지만 아직 범용성 있는 설계가 되어있진 않습니다.
### 설치
@@ -55,9 +52,9 @@ Database 수는 로그인 관리 서버 1개, 내부 서버 7개로, 총 8개의
## 카카오로그인 연동
서버 설치 시 카카오 로그인 연동을 위한 API KEY를 입력습니다.
현재 카카오로그인 API KEY를 입력하는 작업이 설치과정에 추가되어있지 않습니다.
만약 설치 이후 API KEY를 변경하고자 하는 경우 <code>d_setting/KakaoKey.php</code>에서 API키를 변경해야 합니다.
설치 후 <code>d_setting/KakaoKey.php</code>에서 API키를 입력해야 합니다.
## 라이선스
-16
View File
@@ -1,16 +0,0 @@
<?php
namespace sammo;
require(__DIR__ . '/vendor/autoload.php');
if (!class_exists('\\sammo\\RootDB')) {
Json::dieWithReason('No DB');
}
$eParams = $_GET;
if(key_exists('path', $eParams)){
unset($eParams['path']);
}
APIHelper::launch(dirname(__FILE__), $_GET['path']??'', $eParams, true);
+45 -53
View File
@@ -1,53 +1,45 @@
{
"name":"sammo-hid/sammo",
"description":"삼국지 모의전투 HiDCHe",
"license": [
"MIT",
"GPL-2.0-or-later",
"proprietary"
],
"config": {
"platform": {
"php": "8.1"
}
},
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^6.0",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^2.1",
"phan/phan": "^5.3",
"nette/caching": "^3.0",
"illuminate/database": "^9.12",
"illuminate/events": "^9.12",
"spatie/data-transfer-object": "^3.7",
"php-ds/php-ds": "^1.4"
},
"autoload": {
"psr-4": {
"sammo\\": [
"d_setting",
"src/sammo"
],
"kakao\\": [
"d_setting",
"src/kakao"
]
},
"exclude-from-classmap": [
"**/*.orig.php"
],
"files":[
"f_config/config.php"
]
},
"require-dev": {
"phpunit/phpunit": "^9.5"
}
}
{
"name":"sammo-hid/sammo",
"description":"삼국지 모의전투 HiDCHe",
"license": [
"MIT",
"GPL-2.0-or-later",
"proprietary"
],
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"guzzlehttp/guzzle": "^6.3",
"leafo/scssphp": "^0.7.5",
"monolog/monolog": "^1.23",
"firephp/firephp-core": "^0.4.0",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^4.1",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5"
},
"autoload": {
"psr-4": {
"sammo\\": [
"src/sammo"
],
"kakao\\": [
"src/kakao"
]
},
"classmap": [
"d_setting/"
],
"exclude-from-classmap": [
"**/*.orig.php"
],
"files":[
"f_config/config.php"
]
}
}
Generated
+304 -4675
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+170 -245
View File
@@ -1,246 +1,171 @@
@charset "utf-8";
body {
color: white;
background-color: black;
font-family: 'Pretendard';
}
table {
border: solid 1px;
border-spacing: 0px;
border-collapse: separate;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
padding: 0px;
font-size: 14px;
word-break: break-all;
text-align: center;
}
th,
td {
border: solid 1px;
border-spacing: 0px;
border-collapse: separate;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
padding: 0px;
font-size: 14px;
word-break: break-all;
text-align: center;
}
a.just_link {
text-decoration: none;
}
.with_border {
margin: 0;
border: solid 1px;
border-spacing: 0px;
border-collapse: separate;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
}
.section_title {
height: 50px;
line-height: 50px;
font-size: 30px;
font-weight: bold;
text-align: center;
color: white;
padding: 0;
}
.legacy_layout div {
border: solid 1px;
border-spacing: 0px;
border-collapse: separate;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
padding: 0px;
font-size: 14px;
word-break: break-all;
text-align: center;
}
.obj_fill {
display: block;
width: 100%;
height: 100%;
}
button.with_skin {
padding: 0 4px;
background-color: #191919;
color: white;
font-size: 14px;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
}
button.with_skin:disabled {
background-color: #333;
}
input.with_skin {
background-color: #191919;
color: white;
font-size: 14px;
}
input.with_skin[type=button], input.with_skin[type=submit]{
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
}
input.with_skin:disabled {
background-color: #333;
}
.font0 {
font-size: 10px;
}
.font1 {
font-size: 14px;
}
.font2 {
font-size: 15px;
}
.font3 {
font-size: 20px;
}
.font4 {
font-size: 30px;
}
.font5 {
font-size: 50px;
}
caption.section_title {
caption-side: top;
}
.samButton {
float: left;
display: block;
padding: 0;
margin: 0;
text-decoration: none;
position: relative;
}
a.samButton.disabled {
pointer-events: none;
cursor: default;
}
.samButtonOuter {
display: table;
border: outset 2px white;
box-sizing: border-box;
font-weight: bold;
padding: 1px 6px;
width: 125px;
height: 30px;
background-color: #000000;
color: #ffffff;
}
.samButtonOuter:active {
border: inset 2px white;
}
.samButtonInner {
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
user-select: none;
}
.samToolbarButton>.samButtonOuter {
width: 125px;
height: 30px;
background-color: #225500;
color: white;
}
.samToolbarButton2>.samButtonOuter {
width: 125px;
height: 30px;
background-color: #225500;
color: magenta;
}
.samCommandButton>.samButtonOuter {
width: 111px;
height: 30px;
}
.samCommandButton.disabled>.samButtonOuter {
background-color: transparent !important;
color: gray !important;
border-color: transparent !important;
}
.samCommandButton.disabled>.samButtonOuter>.samButtonInner::before {
content: '【'
}
.samCommandButton.disabled>.samButtonOuter>.samButtonInner::after {
content: '】'
}
.tooltip_copyable_info .tooltiptext {
display: inline;
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.tooltiptext {
display: none;
}
.hidden_but_copyable {
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.vertical_flex {
height: 100%;
display: flex;
align-content: center;
flex-direction: column;
align-items: stretch;
}
.vertical_flex .item {
display: block;
flex-grow: 1;
}
.fill_box {
display: block;
width: 100%;
height: 100%;
@charset "utf-8";
body {
color:white; background-color:black; font-family: '맑은 고딕';
}
table {
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black;
padding: 0px;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
}
th, td {
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black;
padding: 0px;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
}
a.just_link {
text-decoration: none;
}
.with_border{
margin:0;
border: solid 1px;
border-spacing: 0px;
border-collapse: separate;
border-top-color: gray;
border-left-color: gray;
border-right-color: black;
border-bottom-color: black;
}
.section_title {
height:50px;
line-height:50px;
font-size: 30px; font-weight: bold;
text-align: center;
color:white;
padding:0;
}
.legacy_layout div {
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black;
padding: 0px;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';;
}
.obj_fill{
display:block;
width:100%;
height:100%;
}
button.with_skin {
padding:0 4px;
background-color: black; color: white;
font-family: '맑은 고딕';
font-size: 13px;
}
button.with_skin:disabled {
background-color:#333333;
}
input.with_skin {
background-color: black; color: white;
font-family: '맑은 고딕';
font-size: 13px;
}
input.with_skin:disabled {
background-color: #333333;
}
.font0 { font-size: 10px; }
.font1 { font-size: 13px; }
.font2 { font-size: 15px; }
.font3 { font-size: 20px; }
.font4 { font-size: 30px; }
.font5 { font-size: 50px; }
caption.section_title {
caption-side:top;
}
.samButton{
float:left;
display:block;
padding:0;
margin:0;
text-decoration: none;
position:relative;
}
a.samButton.disabled {
pointer-events: none;
cursor: default;
}
.samButtonOuter{
display: table;
border: outset 2px white;
box-sizing: border-box;
font-weight:bold;
padding: 1px 6px;
width:125px;
height:30px;
background-color:#000000;
color:#ffffff;
}
.samButtonOuter:active{
border: inset 2px white;
}
.samButtonInner{
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
user-select: none;
}
.samToolbarButton > .samButtonOuter{
width:125px;
height:30px;
background-color:#225500;
color:white;
}
.samToolbarButton2 > .samButtonOuter{
width:125px;
height:30px;
background-color:#225500;
color:magenta;
}
.samCommandButton > .samButtonOuter{
width:111px;
height:30px;
}
.samCommandButton.disabled > .samButtonOuter{
background-color:transparent !important;
color:gray !important;
border-color:transparent !important;
}
.samCommandButton.disabled > .samButtonOuter > .samButtonInner::before{
content:'【'
}
.samCommandButton.disabled > .samButtonOuter > .samButtonInner::after{
content:'】'
}
.tooltiptext {
display: none;
}
+140 -160
View File
@@ -1,161 +1,141 @@
@charset "utf-8";
body {
line-height: 1.3;
}
#server_notice {
margin: 10px 0;
border: none;
text-align: center;
}
#server_list_container {
width: 800px;
position: absolute;
left: 50%;
margin-left: -400px;
}
#server_list_table {
width: 100%;
}
#server_list tr {
height: 66px;
}
.ignore_border {
border: 0;
margin: 0;
padding: 0;
}
#user_info {
margin-top: 20px;
width: 800px;
height: 130px;
}
#user_info .btn {
width: 200px;
margin: 10px 50px;
padding: 10px;
}
.center_ordered_items {
text-align: center;
}
.server-action{
padding-top: 16px;
padding-bottom: 16px;
}
.Entrance_ServerList {
width: 800px;
height: 64px;
border: none;
float: left;
}
.Entrance_ServerListServer {
width: 98px;
height: 64px;
float: left;
}
.Entrance_ServerListDown {
width: 698px;
height: 64px;
float: left;
}
.Entrance_ServerListInfo {
width: 398px;
height: 64px;
float: left;
}
.Entrance_ServerListBlock {
width: 298px;
height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListCharacter {
width: 64px;
height: 64px;
float: left;
}
.Entrance_ServerListName {
width: 112px;
height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListSelect {
width: 120px;
height: 32px;
float: left;
}
#Entrance_000003 {
width: 798px;
height: 155px;
text-align: left;
}
.Entrance_Alert {
color: red;
font-size: 15px;
font-weight: bold;
}
.Entrance_Che {
color: white;
font-size: 15px;
font-weight: bold;
}
.Entrance_Kwe {
color: yellow;
font-size: 15px;
font-weight: bold;
}
.Entrance_Pwe {
color: orange;
font-size: 15px;
font-weight: bold;
}
.Entrance_Twe {
color: magenta;
font-size: 15px;
font-weight: bold;
}
.Entrance_Nya {
color: #e67e22;
font-size: 15px;
font-weight: bold;
}
.Entrance_Pya {
color: #9b59b6;
font-size: 15px;
font-weight: bold;
}
.Entrance_Hwe {
color: red;
font-size: 15px;
font-weight: bold;
}
.BtnPlate {
height: inherit;
@charset "utf-8";
body{
line-height: 1.3;
}
#server_notice {
margin:10px 0;
border: none;
text-align:center;
}
#server_list_container{
width:800px;
position:absolute;
left:50%;
margin-left:-400px;
}
#server_list_table{
width:100%;
}
#server_list tr{
height:66px;
}
#server_list .server_create_and_select .general_create,
#server_list .server_create_and_select .general_select {
width: 120px; height: 33px;
float: left;
}
#server_list .general_create,
#server_list .general_login {
width: 120px; height: 66px;
float: left;
}
.ignore_border{
border:0;
margin:0;
padding:0;
}
#user_info {
margin-top:20px;
width: 800px; height: 130px;
}
#user_info button{
width: 200px;
height: 50px;
margin: 10px 50px;
}
.center_ordered_items{
text-align:center;
}
.Entrance_ServerList {
width: 800px; height: 64px;
border: none;
float: left;
}
.Entrance_ServerListServer {
width: 98px; height: 64px;
float: left;
}
.Entrance_ServerListDown {
width: 698px; height: 64px;
float: left;
}
.Entrance_ServerListInfo {
width: 398px; height: 64px;
float: left;
}
.Entrance_ServerListBlock {
width: 298px; height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListCharacter {
width: 64px; height: 64px;
float: left;
}
.Entrance_ServerListName {
width: 112px; height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListSelect {
width: 120px; height: 32px;
float: left;
}
#Entrance_000003 {
width: 798px; height: 155px;
text-align: left;
}
.Entrance_Alert {
color: red; font-size: 15px; font-weight: bold;
}
.Entrance_Che {
color: white; font-size: 15px; font-weight: bold;
}
.Entrance_Kwe {
color: yellow; font-size: 15px; font-weight: bold;
}
.Entrance_Pwe {
color: orange; font-size: 15px; font-weight: bold;
}
.Entrance_Twe {
color: magenta; font-size: 15px; font-weight: bold;
}
.Entrance_Nya {
color: #e67e22; font-size: 15px; font-weight: bold;
}
.Entrance_Pya {
color: #9b59b6; font-size: 15px; font-weight: bold;
}
.Entrance_Hwe {
color: red; font-size: 15px; font-weight: bold;
}
+3 -3
View File
@@ -7,10 +7,10 @@ body, html{
margin-top: 70px;
}
h1.title {
h1.title {
font-size: 50px;
font-family: 'Pretendard', 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic';
font-weight: 400;
font-family: 'Passion One', cursive;
font-weight: 400;
}
hr{
+3 -3
View File
@@ -7,10 +7,10 @@
margin-top: 70px;
}
h1.title {
h1.title {
font-size: 50px;
font-family: 'Pretendard', 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic';
font-weight: 400;
font-family: 'Passion One', cursive;
font-weight: 400;
}
hr{
+131
View File
@@ -0,0 +1,131 @@
body, html{
height: 100%;
background-repeat: no-repeat;
}
.main{
margin-top: 70px;
}
h1.title {
font-size: 50px;
font-family: 'Passion One', cursive;
font-weight: 400;
}
hr{
width: 10%;
/*color: #fff;*/
}
.form-group{
margin-bottom: 15px;
}
label{
margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder {
font-size: 11px;
padding-top: 3px;
}
.main-login{
/*background-color: #fff;*/
/* shadows and rounded borders */
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.main-center{
margin-top: 30px;
margin: 0 auto;
max-width: 330px;
padding: 40px 40px;
}
.login_btn_group{
margin-top: 5px;
}
.login-register{
font-size: 11px;
text-align: center;
}
.col-form-label{
text-align:center;
}
.terms{
max-height: 200px; overflow-y: auto;
}
.terms pre{
width:100%;
white-space: pre-wrap; /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
.vertical-center {
min-height: 100%; /* Fallback for browsers do NOT support vh unit */
min-height: 100vh; /* These two lines are counted as one :-) */
display: flex;
align-items: center;
}
.full-content {
position:fixed;
left:0;
top:0;
width:100%;
height:100%;
margin:0;
padding:0;
z-index:800;
}
#login_card{
z-index:801;
}
#btn_kakao_login{
cursor: pointer;
height:46px;
width:116px;
background-color: transparent;
color:transparent;
border:0;
background-size: 100%; /* To fill the dimensions of container (button), or */
background-repeat: no-repeat;
background-position: bottom center;
margin-top:5px;
background-image:url('../oauth_kakao/kakao_login_join.png');
}
#btn_kakao_login:hover {
background-image:url('../oauth_kakao/kakao_login_join_ov.png');
}
#bottom_box{
position:fixed;
bottom:0;
width:100%;
left:0;
}
#bottom_box .container{
text-align:center;
}
+1
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
+7
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+12
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+132
View File
@@ -0,0 +1,132 @@
//download.js v3.0, by dandavis; 2008-2014. [CCBY2] see http://danml.com/download.html for tests/usage
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support
// data can be a string, Blob, File, or dataURL
function download(data, strFileName, strMimeType) {
var self = window, // this script is only for browsers anyway...
u = "application/octet-stream", // this default mime also triggers iframe downloads
m = strMimeType || u,
x = data,
D = document,
a = D.createElement("a"),
z = function(a){return String(a);},
B = self.Blob || self.MozBlob || self.WebKitBlob || z,
BB = self.MSBlobBuilder || self.WebKitBlobBuilder || self.BlobBuilder,
fn = strFileName || "download",
blob,
b,
ua,
fr;
//if(typeof B.bind === 'function' ){ B=B.bind(self); }
if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
x=[x, m];
m=x[0];
x=x[1];
}
//go ahead and download dataURLs right away
if(String(x).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/)){
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
navigator.msSaveBlob(d2b(x), fn) :
saver(x) ; // everyone else can save dataURLs un-processed
}//end if dataURL passed?
try{
blob = x instanceof B ?
x :
new B([x], {type: m}) ;
}catch(y){
if(BB){
b = new BB();
b.append([x]);
blob = b.getBlob(m); // the blob
}
}
function d2b(u) {
var p= u.split(/[:;,]/),
t= p[1],
dec= p[2] == "base64" ? atob : decodeURIComponent,
bin= dec(p.pop()),
mx= bin.length,
i= 0,
uia= new Uint8Array(mx);
for(i;i<mx;++i) uia[i]= bin.charCodeAt(i);
return new B([uia], {type: t});
}
function saver(url, winMode){
if ('download' in a) { //html5 A[download]
a.href = url;
a.setAttribute("download", fn);
a.innerHTML = "downloading...";
D.body.appendChild(a);
setTimeout(function() {
a.click();
D.body.removeChild(a);
if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(a.href);}, 250 );}
}, 66);
return true;
}
//do iframe dataURL download (old ch+FF):
var f = D.createElement("iframe");
D.body.appendChild(f);
if(!winMode){ // force a mime that will download:
url="data:"+url.replace(/^data:([\w\/\-\+]+)/, u);
}
f.src = url;
setTimeout(function(){ D.body.removeChild(f); }, 333);
}//end saver
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
return navigator.msSaveBlob(blob, fn);
}
if(self.URL){ // simple fast and modern way using Blob and URL:
saver(self.URL.createObjectURL(blob), true);
}else{
// handle non-Blob()+non-URL browsers:
if(typeof blob === "string" || blob.constructor===z ){
try{
return saver( "data:" + m + ";base64," + self.btoa(blob) );
}catch(y){
return saver( "data:" + m + "," + encodeURIComponent(blob) );
}
}
// Blob but not URL:
fr=new FileReader();
fr.onload=function(e){
saver(this.result);
};
fr.readAsDataURL(blob);
}
return true;
} /* end download() */
Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

+2
View File
File diff suppressed because one or more lines are too long
+7
View File
File diff suppressed because one or more lines are too long
+13
View File
File diff suppressed because one or more lines are too long
+152
View File
@@ -0,0 +1,152 @@
/*
jQuery Redirect v1.1.1
Copyright (c) 2013-2017 Miguel Galante
Copyright (c) 2011-2013 Nemanja Avramovic, www.avramovic.info
Licensed under CC BY-SA 4.0 License: http://creativecommons.org/licenses/by-sa/4.0/
This means everyone is allowed to:
Share - copy and redistribute the material in any medium or format
Adapt - remix, transform, and build upon the material for any purpose, even commercially.
Under following conditions:
Attribution - You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
ShareAlike - If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
*/
(function ($) {
'use strict';
/**
* jQuery Redirect
* @param {string} url - Url of the redirection
* @param {Object} values - (optional) An object with the data to send. If not present will look for values as QueryString in the target url.
* @param {string} method - (optional) The HTTP verb can be GET or POST (defaults to POST)
* @param {string} target - (optional) The target of the form. "_blank" will open the url in a new window.
* @param {boolean} traditional - (optional) This provides the same function as jquery's ajax function. The brackets are omitted on the field name if its an array. This allows arrays to work with MVC.net among others.
* @param {boolean} redirectTop - (optional) If its called from a iframe, force to navigate the top window.
*/
$.redirect = function (url, values, method, target, traditional, redirectTop) {
redirectTop = redirectTop || false;
var generatedForm = $.redirect.getForm(url, values, method, target, traditional);
$('body', redirectTop ? window.top.document : undefined).append(generatedForm.form);
generatedForm.submit();
};
$.redirect.getForm = function (url, values, method, target, traditional) {
method = (method && ["GET", "POST", "PUT", "DELETE"].indexOf(method.toUpperCase()) !== -1) ? method.toUpperCase() : 'POST';
url = url.split("#");
var hash = url[1] ? ("#" + url[1]) : "";
url = url[0];
if (!values) {
var obj = $.parseUrl(url);
url = obj.url;
values = obj.params;
}
values = removeNulls(values);
var form = $('<form>')
.attr("method", method)
.attr("action", url + hash);
if (target) {
form.attr("target", target);
}
var submit = form[0].submit;
iterateValues(values, [], form, null, traditional);
return { form: form, submit: function () { submit.call(form[0]); } };
}
//Utility Functions
/**
* Url and QueryString Parser.
* @param {string} url - a Url to parse.
* @returns {object} an object with the parsed url with the following structure {url: URL, params:{ KEY: VALUE }}
*/
$.parseUrl = function (url) {
if (url.indexOf('?') === -1) {
return {
url: url,
params: {}
};
}
var parts = url.split('?'),
query_string = parts[1],
elems = query_string.split('&');
url = parts[0];
var i, pair, obj = {};
for (i = 0; i < elems.length; i += 1) {
pair = elems[i].split('=');
obj[pair[0]] = pair[1];
}
return {
url: url,
params: obj
};
};
//Private Functions
var getInput = function (name, value, parent, array, traditional) {
var parentString;
if (parent.length > 0) {
parentString = parent[0];
var i;
for (i = 1; i < parent.length; i += 1) {
parentString += "[" + parent[i] + "]";
}
if (array) {
if (traditional)
name = parentString;
else
name = parentString + "[" + name + "]";
} else {
name = parentString + "[" + name + "]";
}
}
return $("<input>").attr("type", "hidden")
.attr("name", name)
.attr("value", value);
};
var iterateValues = function (values, parent, form, isArray, traditional) {
var i, iterateParent = [];
Object.keys(values).forEach(function (i) {
if (typeof values[i] === "object") {
iterateParent = parent.slice();
iterateParent.push(i);
iterateValues(values[i], iterateParent, form, Array.isArray(values[i]), traditional);
} else {
form.append(getInput(i, values[i], parent, isArray, traditional));
}
});
};
var removeNulls = function (values) {
var propNames = Object.getOwnPropertyNames(values);
for (var i = 0; i < propNames.length; i++) {
var propName = propNames[i];
if (values[propName] === null || values[propName] === undefined) {
delete values[propName];
} else if (typeof values[propName] === 'object') {
values[propName] = removeNulls(values[propName]);
} else if (values[propName].length < 1) {
delete values[propName];
}
}
return values;
};
}(window.jQuery || window.Zepto || window.jqlite));
+4
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
TODO : adobdb5, phpmailer5(?), plates, utilphp
+1
View File
@@ -0,0 +1 @@
"use strict";!function(t,r){var n=function(t){function r(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function n(t){return t.replace(/"/g,"&quot;")}function e(t){if(!t)return"";var r=[];for(var e in t){var i=t[e]+"";r.push(e+'="'+n(i)+'"')}return r.join(" ")}function i(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};i=new a(i);for(var f=o(t),u=[],c=0;c<f.length;c++){var p=f[c];if("nl"===p.type&&i.nl2br)u.push("<br>\n");else if(p.isLink&&i.check(p)){var l=i.resolve(p),s=l.formatted,g=l.formattedHref,y=l.tagName,h=l.className,v=l.target,k=l.attributes,S="<"+y+' href="'+n(g)+'"';h&&(S+=' class="'+n(h)+'"'),v&&(S+=' target="'+n(v)+'"'),k&&(S+=" "+e(k)),S+=">"+r(s)+"</"+y+">",u.push(S)}else u.push(r(p.toString()))}return u.join("")}var o=t.tokenize,f=t.options,a=f.Options;if(!String.prototype.linkify)try{Object.defineProperty(String.prototype,"linkify",{a:function(){},get:function(){return function(t){return i(this,t)}}})}catch(u){String.prototype.linkify||(String.prototype.linkify=function(t){return i(this,t)})}return i}(r);t.linkifyStr=n}(window,linkify);
+1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,3 +1,3 @@
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
/*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}();
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="너무 깁니다. "+t+" 글자 지워주세요.";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="너무 짧습니다. "+t+" 글자 더 입력해주세요.";return n},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(e){var t="최대 "+e.maximum+"개까지만 선택 가능합니다.";return t},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"}}}),{define:e.define,require:e.require}})();
+188 -553
View File
@@ -1,553 +1,188 @@
/* select2-bootstrap4 with Darkly */
.select2-container--bootstrap4 {
color: black;
}
.select2-container--bootstrap4 .select2-selection {
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
color: #495057;
font-size: 1rem;
outline: 0;
}
.select2-container--bootstrap4 .select2-selection.form-control {
border-radius: 0.25rem;
}
.select2-container--bootstrap4 .select2-search--dropdown .select2-search__field {
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
color: #495057;
font-size: 1rem;
}
.select2-container--bootstrap4 .select2-search__field {
outline: 0;
}
.select2-container--bootstrap4 .select2-search__field::-webkit-input-placeholder {
color: #6c757d;
}
.select2-container--bootstrap4 .select2-search__field:-moz-placeholder {
color: #6c757d;
}
.select2-container--bootstrap4 .select2-search__field::-moz-placeholder {
color: #6c757d;
opacity: 1;
}
.select2-container--bootstrap4 .select2-search__field:-ms-input-placeholder {
color: #6c757d;
}
.select2-container--bootstrap4 .select2-results__option {
padding: 0.75rem 0.375rem;
font-size: 1rem;
}
.select2-container--bootstrap4 .select2-results__option[role=group] {
padding: 0;
}
.select2-container--bootstrap4 .select2-results__option[aria-disabled=true] {
color: #6c757d;
cursor: not-allowed;
}
.select2-container--bootstrap4 .select2-results__option[aria-selected=true] {
background-color: #f8f9fa;
color: #16181b;
}
.select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] {
background-color: #007bff;
color: #fff;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option {
padding: 0.75rem 0.375rem;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option {
margin-left: -0.375rem;
padding-left: 0.75rem;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -0.75rem;
padding-left: 1.125rem;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1.125rem;
padding-left: 1.5rem;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1.5rem;
padding-left: 1.875rem;
}
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1.875rem;
padding-left: 2.25rem;
}
.select2-container--bootstrap4 .select2-results__group {
color: #6c757d;
display: block;
padding: 0.75rem 0.375rem;
font-size: 75%;
line-height: 1;
white-space: nowrap;
}
.select2-container--bootstrap4.select2-container--focus .select2-selection,
.select2-container--bootstrap4.select2-container--open .select2-selection {
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
border-color: #80bdff;
}
@media screen and (prefers-reduced-motion: reduce) {
.select2-container--bootstrap4.select2-container--focus .select2-selection,
.select2-container--bootstrap4.select2-container--open .select2-selection {
transition: none;
}
}
.select2-container--bootstrap4.select2-container--open .select2-selection .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
border-width: 0 0.25rem 0.25rem 0.25rem;
}
.select2-container--bootstrap4.select2-container--open.select2-container--below .select2-selection {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
border-bottom-color: transparent;
}
.select2-container--bootstrap4.select2-container--open.select2-container--above .select2-selection {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-top-color: transparent;
}
.select2-container--bootstrap4 .select2-selection__clear {
color: #6c757d;
cursor: pointer;
float: right;
font-weight: bold;
margin-right: 10px;
}
.select2-container--bootstrap4 .select2-selection__clear:hover {
color: #343a40;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection {
border-color: #ced4da;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection,
.select2-container--bootstrap4.select2-container--disabled .select2-search__field {
cursor: not-allowed;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection,
.select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice {
background-color: #e9ecef;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection__clear,
.select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove {
display: none;
}
.select2-container--bootstrap4 .select2-dropdown {
border-color: #80bdff;
border-width: 1px;
overflow-x: hidden;
margin-top: -1px;
}
.select2-container--bootstrap4 .select2-dropdown--above {
margin-top: 1px;
}
.select2-container--bootstrap4 .select2-results>.select2-results__options {
max-height: 200px;
overflow-y: auto;
}
.select2-container--bootstrap4 .select2-selection--single {
height: calc(2.25rem + 2px);
line-height: 1;
padding: 0.75rem 1.125rem 0.75rem 0.375rem;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow {
position: absolute;
bottom: 0;
right: 0.375rem;
top: 0;
width: 0.25rem;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
border-color: #6c757d transparent transparent transparent;
border-style: solid;
border-width: 0.25rem 0.25rem 0 0.25rem;
height: 0;
left: 0;
margin-left: -0.25rem;
margin-top: -0.125rem;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered {
color: #495057;
padding: 0;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__placeholder {
color: #6c757d;
}
.select2-container--bootstrap4 .select2-selection--multiple {
min-height: calc(2.25rem + 2px);
padding: 0;
height: auto;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
display: block;
line-height: 1;
list-style: none;
margin: 0;
overflow: hidden;
padding: 0.75rem 0.375rem 0 0.75rem;
width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__placeholder {
color: #6c757d;
float: left;
margin-top: 5px;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice {
color: #495057;
background: transparent;
border: 1px solid #343a40;
border-radius: 0.25rem;
cursor: default;
float: left;
margin: -0.25rem 0 0 0.1875rem;
padding: 0 0.75rem;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field {
background: transparent;
padding: 0 0.375rem;
height: calc(2.25rem + 2px)-2;
line-height: 1;
margin-top: 0;
min-width: 5em;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove {
color: #6c757d;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 0.375rem;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #343a40;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear {
margin-top: 0.75rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-sm,
.input-group-sm .select2-container--bootstrap4 .select2-selection--single,
.form-group-sm .select2-container--bootstrap4 .select2-selection--single {
border-radius: 0.2rem;
font-size: 75%;
height: calc(1.8125rem + 2px);
line-height: 1;
padding: 0.5rem 1rem 0.5rem 0.25rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-sm .select2-selection__arrow b,
.input-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b,
.form-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
margin-left: -0.5rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple {
min-height: calc(1.8125rem + 2px);
border-radius: 0.2rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__rendered,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered {
padding: 0.5rem 0.25rem 0 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__choice,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice {
font-size: 75%;
line-height: 1;
margin: 0 0 0 0.125rem;
padding: 0 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field {
padding: 0 0.25rem;
font-size: 75%;
height: calc(1.8125rem + 2px)-2;
line-height: 1;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__clear,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear {
margin-top: 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg,
.input-group-lg .select2-container--bootstrap4 .select2-selection--single,
.form-group-lg .select2-container--bootstrap4 .select2-selection--single {
border-radius: 0.3rem;
font-size: 1.25rem;
height: calc(2.875rem + 2px);
line-height: 1;
padding: 1rem 1.4375rem 1rem 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow,
.input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow,
.form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow {
width: 0.3125rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow b,
.input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b,
.form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
border-width: 0.3125rem 0.3125rem 0 0.3125rem;
margin-left: -0.3125rem;
margin-left: -1rem;
margin-top: -0.15625rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple {
min-height: calc(2.875rem + 2px);
border-radius: 0.3rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__choice,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice {
font-size: 1.25rem;
line-height: 1;
border-radius: 0.25rem;
margin: 0rem 0 0 0.25rem;
padding: 0 1rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field {
padding: 0 0.5rem;
font-size: 1.25rem;
height: calc(2.875rem + 2px)-2;
line-height: 1;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__clear,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear {
margin-top: 1rem;
}
.select2-container--bootstrap4 .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
border-width: 0 0.3125rem 0.3125rem 0.3125rem;
}
.input-group-lg .select2-container--bootstrap4 .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
border-width: 0 0.3125rem 0.3125rem 0.3125rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single {
padding-left: 1.125rem;
padding-right: 0.375rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 0;
padding-left: 0;
text-align: right;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 0.375rem;
right: auto;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow b {
margin-left: 0;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice,
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 0;
margin-right: 0.1875rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.has-warning .select2-dropdown,
.has-warning .select2-selection {
border-color: #ffc107;
}
.has-warning .select2-container--focus .select2-selection,
.has-warning .select2-container--open .select2-selection {
border-color: #d39e00;
}
.has-warning.select2-drop-active {
border-color: #d39e00;
}
.has-warning.select2-drop-active.select2-drop.select2-drop-above {
border-top-color: #d39e00;
}
.has-error .select2-dropdown,
.has-error .select2-selection {
border-color: #dc3545;
}
.has-error .select2-container--focus .select2-selection,
.has-error .select2-container--open .select2-selection {
border-color: #bd2130;
}
.has-error.select2-drop-active {
border-color: #bd2130;
}
.has-error.select2-drop-active.select2-drop.select2-drop-above {
border-top-color: #bd2130;
}
.has-success .select2-dropdown,
.has-success .select2-selection {
border-color: #28a745;
}
.has-success .select2-container--focus .select2-selection,
.has-success .select2-container--open .select2-selection {
border-color: #1e7e34;
}
.has-success.select2-drop-active {
border-color: #1e7e34;
}
.has-success.select2-drop-active.select2-drop.select2-drop-above {
border-top-color: #1e7e34;
}
.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap4>.selection>.select2-selection,
.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap4>.selection>.select2-selection.form-control {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap4:not(:last-child)>.selection>.select2-selection,
.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap4:not(:last-child)>.selection>.select2-selection.form-control {
border-radius: 0;
}
.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap4:last-child>.selection>.select2-selection,
.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap4:last-child>.selection>.select2-selection.form-control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.input-group>.select2-container--bootstrap4 {
display: table;
table-layout: fixed;
position: relative;
z-index: 2;
width: 100%;
margin-bottom: 0;
}
.input-group>.select2-container--bootstrap4>.selection>.select2-selection.form-control {
float: none;
}
.input-group>.select2-container--bootstrap4.select2-container--open,
.input-group>.select2-container--bootstrap4.select2-container--focus {
z-index: 3;
}
.input-group>.select2-container--bootstrap4,
.input-group>.select2-container--bootstrap4 .input-group-btn,
.input-group>.select2-container--bootstrap4 .input-group-btn .btn {
vertical-align: top;
}
.form-control.select2-hidden-accessible {
position: absolute !important;
width: 1px !important;
}
@media (min-width: 576px) {
.form-inline .select2-container--bootstrap4 {
display: inline-block;
}
}
/* select2-bootstrap4 with Darkly */
.select2-container--bootstrap4 { color: black; }
.select2-container--bootstrap4 .select2-selection { background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; color: #495057; font-size: 1rem; outline: 0; }
.select2-container--bootstrap4 .select2-selection.form-control { border-radius: 0.25rem; }
.select2-container--bootstrap4 .select2-search--dropdown .select2-search__field { background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; color: #495057; font-size: 1rem; }
.select2-container--bootstrap4 .select2-search__field { outline: 0; }
.select2-container--bootstrap4 .select2-search__field::-webkit-input-placeholder { color: #6c757d; }
.select2-container--bootstrap4 .select2-search__field:-moz-placeholder { color: #6c757d; }
.select2-container--bootstrap4 .select2-search__field::-moz-placeholder { color: #6c757d; opacity: 1; }
.select2-container--bootstrap4 .select2-search__field:-ms-input-placeholder { color: #6c757d; }
.select2-container--bootstrap4 .select2-results__option { padding: 0.75rem 0.375rem; font-size: 1rem; }
.select2-container--bootstrap4 .select2-results__option[role=group] { padding: 0; }
.select2-container--bootstrap4 .select2-results__option[aria-disabled=true] { color: #6c757d; cursor: not-allowed; }
.select2-container--bootstrap4 .select2-results__option[aria-selected=true] { background-color: #f8f9fa; color: #16181b; }
.select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] { background-color: #007bff; color: #fff; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option { padding: 0.75rem 0.375rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__group { padding-left: 0; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option { margin-left: -0.375rem; padding-left: 0.75rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -0.75rem; padding-left: 1.125rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -1.125rem; padding-left: 1.5rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -1.5rem; padding-left: 1.875rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -1.875rem; padding-left: 2.25rem; }
.select2-container--bootstrap4 .select2-results__group { color: #6c757d; display: block; padding: 0.75rem 0.375rem; font-size: 75%; line-height: 1; white-space: nowrap; }
.select2-container--bootstrap4.select2-container--focus .select2-selection, .select2-container--bootstrap4.select2-container--open .select2-selection { transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; border-color: #80bdff; }
@media screen and (prefers-reduced-motion: reduce) { .select2-container--bootstrap4.select2-container--focus .select2-selection, .select2-container--bootstrap4.select2-container--open .select2-selection { transition: none; } }
.select2-container--bootstrap4.select2-container--open .select2-selection .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.25rem 0.25rem 0.25rem; }
.select2-container--bootstrap4.select2-container--open.select2-container--below .select2-selection { border-bottom-right-radius: 0; border-bottom-left-radius: 0; border-bottom-color: transparent; }
.select2-container--bootstrap4.select2-container--open.select2-container--above .select2-selection { border-top-left-radius: 0; border-top-right-radius: 0; border-top-color: transparent; }
.select2-container--bootstrap4 .select2-selection__clear { color: #6c757d; cursor: pointer; float: right; font-weight: bold; margin-right: 10px; }
.select2-container--bootstrap4 .select2-selection__clear:hover { color: #343a40; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection { border-color: #ced4da; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection, .select2-container--bootstrap4.select2-container--disabled .select2-search__field { cursor: not-allowed; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection, .select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice { background-color: #e9ecef; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection__clear, .select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove { display: none; }
.select2-container--bootstrap4 .select2-dropdown { border-color: #80bdff; border-width: 1px; overflow-x: hidden; margin-top: -1px; }
.select2-container--bootstrap4 .select2-dropdown--above { margin-top: 1px; }
.select2-container--bootstrap4 .select2-results > .select2-results__options { max-height: 200px; overflow-y: auto; }
.select2-container--bootstrap4 .select2-selection--single { height: calc(2.25rem + 2px); line-height: 1; padding: 0.75rem 1.125rem 0.75rem 0.375rem; }
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow { position: absolute; bottom: 0; right: 0.375rem; top: 0; width: 0.25rem; }
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { border-color: #6c757d transparent transparent transparent; border-style: solid; border-width: 0.25rem 0.25rem 0 0.25rem; height: 0; left: 0; margin-left: -0.25rem; margin-top: -0.125rem; position: absolute; top: 50%; width: 0; }
.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered { color: #495057; padding: 0; }
.select2-container--bootstrap4 .select2-selection--single .select2-selection__placeholder { color: #6c757d; }
.select2-container--bootstrap4 .select2-selection--multiple { min-height: calc(2.25rem + 2px); padding: 0; height: auto; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered { box-sizing: border-box; display: block; line-height: 1; list-style: none; margin: 0; overflow: hidden; padding: 0.75rem 0.375rem 0 0.75rem; width: 100%; text-overflow: ellipsis; white-space: nowrap; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__placeholder { color: #6c757d; float: left; margin-top: 5px; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { color: #495057; background: transparent; border: 1px solid #343a40; border-radius: 0.25rem; cursor: default; float: left; margin: -0.25rem 0 0 0.1875rem; padding: 0 0.75rem; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field { background: transparent; padding: 0 0.375rem; height: calc(2.25rem + 2px)-2; line-height: 1; margin-top: 0; min-width: 5em; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove { color: #6c757d; cursor: pointer; display: inline-block; font-weight: bold; margin-right: 0.375rem; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove:hover { color: #343a40; }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear { margin-top: 0.75rem; }
.select2-container--bootstrap4 .select2-selection--single.input-sm, .input-group-sm .select2-container--bootstrap4 .select2-selection--single, .form-group-sm .select2-container--bootstrap4 .select2-selection--single { border-radius: 0.2rem; font-size: 75%; height: calc(1.8125rem + 2px); line-height: 1; padding: 0.5rem 1rem 0.5rem 0.25rem; }
.select2-container--bootstrap4 .select2-selection--single.input-sm .select2-selection__arrow b, .input-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b, .form-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { margin-left: -0.5rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-sm, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple { min-height: calc(1.8125rem + 2px); border-radius: 0.2rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__rendered, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered { padding: 0.5rem 0.25rem 0 0.5rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__choice, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { font-size: 75%; line-height: 1; margin: 0 0 0 0.125rem; padding: 0 0.5rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field { padding: 0 0.25rem; font-size: 75%; height: calc(1.8125rem + 2px)-2; line-height: 1; }
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__clear, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear { margin-top: 0.5rem; }
.select2-container--bootstrap4 .select2-selection--single.input-lg, .input-group-lg .select2-container--bootstrap4 .select2-selection--single, .form-group-lg .select2-container--bootstrap4 .select2-selection--single { border-radius: 0.3rem; font-size: 1.25rem; height: calc(2.875rem + 2px); line-height: 1; padding: 1rem 1.4375rem 1rem 0.5rem; }
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow, .input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow, .form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow { width: 0.3125rem; }
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow b, .input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b, .form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { border-width: 0.3125rem 0.3125rem 0 0.3125rem; margin-left: -0.3125rem; margin-left: -1rem; margin-top: -0.15625rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-lg, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple { min-height: calc(2.875rem + 2px); border-radius: 0.3rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__choice, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { font-size: 1.25rem; line-height: 1; border-radius: 0.25rem; margin: 0rem 0 0 0.25rem; padding: 0 1rem; }
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field { padding: 0 0.5rem; font-size: 1.25rem; height: calc(2.875rem + 2px)-2; line-height: 1; }
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__clear, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear { margin-top: 1rem; }
.select2-container--bootstrap4 .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.3125rem 0.3125rem 0.3125rem; }
.input-group-lg .select2-container--bootstrap4 .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.3125rem 0.3125rem 0.3125rem; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single { padding-left: 1.125rem; padding-right: 0.375rem; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__rendered { padding-right: 0; padding-left: 0; text-align: right; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__clear { float: left; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow { left: 0.375rem; right: auto; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow b { margin-left: 0; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-search--inline { float: right; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice { margin-left: 0; margin-right: 0.1875rem; }
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { margin-left: 2px; margin-right: auto; }
.has-warning .select2-dropdown, .has-warning .select2-selection { border-color: #ffc107; }
.has-warning .select2-container--focus .select2-selection, .has-warning .select2-container--open .select2-selection { border-color: #d39e00; }
.has-warning.select2-drop-active { border-color: #d39e00; }
.has-warning.select2-drop-active.select2-drop.select2-drop-above { border-top-color: #d39e00; }
.has-error .select2-dropdown, .has-error .select2-selection { border-color: #dc3545; }
.has-error .select2-container--focus .select2-selection, .has-error .select2-container--open .select2-selection { border-color: #bd2130; }
.has-error.select2-drop-active { border-color: #bd2130; }
.has-error.select2-drop-active.select2-drop.select2-drop-above { border-top-color: #bd2130; }
.has-success .select2-dropdown, .has-success .select2-selection { border-color: #28a745; }
.has-success .select2-container--focus .select2-selection, .has-success .select2-container--open .select2-selection { border-color: #1e7e34; }
.has-success.select2-drop-active { border-color: #1e7e34; }
.has-success.select2-drop-active.select2-drop.select2-drop-above { border-top-color: #1e7e34; }
.input-group > .select2-hidden-accessible:first-child + .select2-container--bootstrap4 > .selection > .select2-selection, .input-group > .select2-hidden-accessible:first-child + .select2-container--bootstrap4 > .selection > .select2-selection.form-control { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.input-group > .select2-hidden-accessible:not(:first-child) + .select2-container--bootstrap4:not(:last-child) > .selection > .select2-selection, .input-group > .select2-hidden-accessible:not(:first-child) + .select2-container--bootstrap4:not(:last-child) > .selection > .select2-selection.form-control { border-radius: 0; }
.input-group > .select2-hidden-accessible:not(:first-child):not(:last-child) + .select2-container--bootstrap4:last-child > .selection > .select2-selection, .input-group > .select2-hidden-accessible:not(:first-child):not(:last-child) + .select2-container--bootstrap4:last-child > .selection > .select2-selection.form-control { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.input-group > .select2-container--bootstrap4 { display: table; table-layout: fixed; position: relative; z-index: 2; width: 100%; margin-bottom: 0; }
.input-group > .select2-container--bootstrap4 > .selection > .select2-selection.form-control { float: none; }
.input-group > .select2-container--bootstrap4.select2-container--open, .input-group > .select2-container--bootstrap4.select2-container--focus { z-index: 3; }
.input-group > .select2-container--bootstrap4, .input-group > .select2-container--bootstrap4 .input-group-btn, .input-group > .select2-container--bootstrap4 .input-group-btn .btn { vertical-align: top; }
.form-control.select2-hidden-accessible { position: absolute !important; width: 1px !important; }
@media (min-width: 576px) { .form-inline .select2-container--bootstrap4 { display: inline-block; } }
+11 -8
View File
@@ -118,14 +118,12 @@
.select2-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
margin: -1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important; }
width: 1px !important; }
.select2-container--default .select2-selection--single {
background-color: #fff;
@@ -188,13 +186,16 @@
width: 100%; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none; }
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
color: #999;
margin-top: 5px;
float: left; }
.select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px;
padding: 1px; }
margin-right: 10px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
@@ -213,7 +214,7 @@
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
@@ -419,7 +420,9 @@
color: #555; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right;
float: right; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto; }
+220 -583
View File
@@ -1,11 +1,11 @@
/*!
* Select2 4.0.13
* Select2 4.0.5
* https://select2.github.io
*
* Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md
*/
;(function (factory) {
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
@@ -574,10 +574,10 @@ S2.define('select2/utils',[
DecoratedClass.prototype = new ctr();
for (var m = 0; m < superMethods.length; m++) {
var superMethod = superMethods[m];
var superMethod = superMethods[m];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
}
var calledMethod = function (methodName) {
@@ -772,70 +772,6 @@ S2.define('select2/utils',[
$element.append($nodes);
};
// Cache objects in Utils.__cache instead of $.data (see #4346)
Utils.__cache = {};
var id = 0;
Utils.GetUniqueElementId = function (element) {
// Get a unique element Id. If element has no id,
// creates a new unique number, stores it in the id
// attribute and returns the new id.
// If an id already exists, it simply returns it.
var select2Id = element.getAttribute('data-select2-id');
if (select2Id == null) {
// If element has id, use it.
if (element.id) {
select2Id = element.id;
element.setAttribute('data-select2-id', select2Id);
} else {
element.setAttribute('data-select2-id', ++id);
select2Id = id.toString();
}
}
return select2Id;
};
Utils.StoreData = function (element, name, value) {
// Stores an item in the cache for a specified element.
// name is the cache key.
var id = Utils.GetUniqueElementId(element);
if (!Utils.__cache[id]) {
Utils.__cache[id] = {};
}
Utils.__cache[id][name] = value;
};
Utils.GetData = function (element, name) {
// Retrieves a value from the cache by its key (name)
// name is optional. If no name specified, return
// all cache items for the specified element.
// and for a specified element.
var id = Utils.GetUniqueElementId(element);
if (name) {
if (Utils.__cache[id]) {
if (Utils.__cache[id][name] != null) {
return Utils.__cache[id][name];
}
return $(element).data(name); // Fallback to HTML5 data attribs.
}
return $(element).data(name); // Fallback to HTML5 data attribs.
} else {
return Utils.__cache[id];
}
};
Utils.RemoveData = function (element) {
// Removes all cached items for a specified element.
var id = Utils.GetUniqueElementId(element);
if (Utils.__cache[id] != null) {
delete Utils.__cache[id];
}
element.removeAttribute('data-select2-id');
};
return Utils;
});
@@ -855,7 +791,7 @@ S2.define('select2/results',[
Results.prototype.render = function () {
var $results = $(
'<ul class="select2-results__options" role="listbox"></ul>'
'<ul class="select2-results__options" role="tree"></ul>'
);
if (this.options.get('multiple')) {
@@ -878,7 +814,7 @@ S2.define('select2/results',[
this.hideLoading();
var $message = $(
'<li role="alert" aria-live="assertive"' +
'<li role="treeitem" aria-live="assertive"' +
' class="select2-results__option"></li>'
);
@@ -971,7 +907,7 @@ S2.define('select2/results',[
$options.each(function () {
var $option = $(this);
var item = Utils.GetData(this, 'data');
var item = $.data(this, 'data');
// id needs to be converted to a string when comparing
var id = '' + item.id;
@@ -1012,16 +948,11 @@ S2.define('select2/results',[
option.className = 'select2-results__option';
var attrs = {
'role': 'option',
'role': 'treeitem',
'aria-selected': 'false'
};
var matches = window.Element.prototype.matches ||
window.Element.prototype.msMatchesSelector ||
window.Element.prototype.webkitMatchesSelector;
if ((data.element != null && matches.call(data.element, ':disabled')) ||
(data.element == null && data.disabled)) {
if (data.disabled) {
delete attrs['aria-selected'];
attrs['aria-disabled'] = 'true';
}
@@ -1081,7 +1012,7 @@ S2.define('select2/results',[
this.template(data, option);
}
Utils.StoreData(option, 'data', data);
$.data(option, 'data', data);
return option;
};
@@ -1122,10 +1053,7 @@ S2.define('select2/results',[
}
self.setClasses();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
self.highlightFirstItem();
});
container.on('unselect', function () {
@@ -1134,10 +1062,7 @@ S2.define('select2/results',[
}
self.setClasses();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
self.highlightFirstItem();
});
container.on('open', function () {
@@ -1173,7 +1098,7 @@ S2.define('select2/results',[
return;
}
var data = Utils.GetData($highlighted[0], 'data');
var data = $highlighted.data('data');
if ($highlighted.attr('aria-selected') == 'true') {
self.trigger('close', {});
@@ -1191,9 +1116,8 @@ S2.define('select2/results',[
var currentIndex = $options.index($highlighted);
// If we are already at the top, don't move further
// If no options, currentIndex will be -1
if (currentIndex <= 0) {
// If we are already at te top, don't move further
if (currentIndex === 0) {
return;
}
@@ -1286,7 +1210,7 @@ S2.define('select2/results',[
function (evt) {
var $this = $(this);
var data = Utils.GetData(this, 'data');
var data = $this.data('data');
if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) {
@@ -1309,7 +1233,7 @@ S2.define('select2/results',[
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
function (evt) {
var data = Utils.GetData(this, 'data');
var data = $(this).data('data');
self.getHighlightedResults()
.removeClass('select2-results__option--highlighted');
@@ -1424,15 +1348,14 @@ S2.define('select2/selection/base',[
this._tabindex = 0;
if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
if (this.$element.data('old-tabindex') != null) {
this._tabindex = this.$element.data('old-tabindex');
} else if (this.$element.attr('tabindex') != null) {
this._tabindex = this.$element.attr('tabindex');
}
$selection.attr('title', this.$element.attr('title'));
$selection.attr('tabindex', this._tabindex);
$selection.attr('aria-disabled', 'false');
this.$selection = $selection;
@@ -1442,6 +1365,7 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.bind = function (container, $container) {
var self = this;
var id = container.id + '-container';
var resultsId = container.id + '-results';
this.container = container;
@@ -1484,19 +1408,17 @@ S2.define('select2/selection/base',[
self.$selection.removeAttr('aria-activedescendant');
self.$selection.removeAttr('aria-owns');
self.$selection.trigger('focus');
self.$selection.focus();
self._detachCloseHandler(container);
});
container.on('enable', function () {
self.$selection.attr('tabindex', self._tabindex);
self.$selection.attr('aria-disabled', 'false');
});
container.on('disable', function () {
self.$selection.attr('tabindex', '-1');
self.$selection.attr('aria-disabled', 'true');
});
};
@@ -1519,6 +1441,7 @@ S2.define('select2/selection/base',[
};
BaseSelection.prototype._attachCloseHandler = function (container) {
var self = this;
$(document.body).on('mousedown.select2.' + container.id, function (e) {
var $target = $(e.target);
@@ -1528,11 +1451,13 @@ S2.define('select2/selection/base',[
var $all = $('.select2.select2-container--open');
$all.each(function () {
var $this = $(this);
if (this == $select[0]) {
return;
}
var $element = Utils.GetData(this, 'element');
var $element = $this.data('element');
$element.select2('close');
});
@@ -1556,27 +1481,6 @@ S2.define('select2/selection/base',[
throw new Error('The `update` method must be defined in child classes.');
};
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
BaseSelection.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
BaseSelection.prototype.isDisabled = function () {
return this.options.get('disabled');
};
return BaseSelection;
});
@@ -1614,10 +1518,7 @@ S2.define('select2/selection/single',[
var id = container.id + '-container';
this.$selection.find('.select2-selection__rendered')
.attr('id', id)
.attr('role', 'textbox')
.attr('aria-readonly', 'true');
this.$selection.find('.select2-selection__rendered').attr('id', id);
this.$selection.attr('aria-labelledby', id);
this.$selection.on('mousedown', function (evt) {
@@ -1641,15 +1542,17 @@ S2.define('select2/selection/single',[
container.on('focus', function (evt) {
if (!container.isOpen()) {
self.$selection.trigger('focus');
self.$selection.focus();
}
});
container.on('selection:update', function (params) {
self.update(params.data);
});
};
SingleSelection.prototype.clear = function () {
var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title'); // clear tooltip on empty
this.$selection.find('.select2-selection__rendered').empty();
};
SingleSelection.prototype.display = function (data, container) {
@@ -1675,14 +1578,7 @@ S2.define('select2/selection/single',[
var formatted = this.display(selection, $rendered);
$rendered.empty().append(formatted);
var title = selection.title || selection.text;
if (title) {
$rendered.attr('title', title);
} else {
$rendered.removeAttr('title');
}
$rendered.prop('title', selection.title || selection.text);
};
return SingleSelection;
@@ -1727,14 +1623,14 @@ S2.define('select2/selection/multiple',[
'.select2-selection__choice__remove',
function (evt) {
// Ignore the event if it is disabled
if (self.isDisabled()) {
if (self.options.get('disabled')) {
return;
}
var $remove = $(this);
var $selection = $remove.parent();
var data = Utils.GetData($selection[0], 'data');
var data = $selection.data('data');
self.trigger('unselect', {
originalEvent: evt,
@@ -1745,9 +1641,7 @@ S2.define('select2/selection/multiple',[
};
MultipleSelection.prototype.clear = function () {
var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title');
this.$selection.find('.select2-selection__rendered').empty();
};
MultipleSelection.prototype.display = function (data, container) {
@@ -1785,14 +1679,9 @@ S2.define('select2/selection/multiple',[
var formatted = this.display(selection, $selection);
$selection.append(formatted);
$selection.prop('title', selection.title || selection.text);
var title = selection.title || selection.text;
if (title) {
$selection.attr('title', title);
}
Utils.StoreData($selection[0], 'data', selection);
$selection.data('data', selection);
$selections.push($selection);
}
@@ -1857,9 +1746,8 @@ S2.define('select2/selection/placeholder',[
S2.define('select2/selection/allowClear',[
'jquery',
'../keys',
'../utils'
], function ($, KEYS, Utils) {
'../keys'
], function ($, KEYS) {
function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -1888,7 +1776,7 @@ S2.define('select2/selection/allowClear',[
AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled
if (this.isDisabled()) {
if (this.options.get('disabled')) {
return;
}
@@ -1901,22 +1789,10 @@ S2.define('select2/selection/allowClear',[
evt.stopPropagation();
var data = Utils.GetData($clear[0], 'data');
var previousVal = this.$element.val();
this.$element.val(this.placeholder.id);
var unselectData = {
data: data
};
this.trigger('clear', unselectData);
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
var data = $clear.data('data');
for (var d = 0; d < data.length; d++) {
unselectData = {
var unselectData = {
data: data[d]
};
@@ -1926,12 +1802,11 @@ S2.define('select2/selection/allowClear',[
// If the event was prevented, don't clear it out.
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
}
this.$element.trigger('input').trigger('change');
this.$element.val(this.placeholder.id).trigger('change');
this.trigger('toggle', {});
};
@@ -1954,14 +1829,12 @@ S2.define('select2/selection/allowClear',[
return;
}
var removeAll = this.options.get('translations').get('removeAllItems');
var $remove = $(
'<span class="select2-selection__clear" title="' + removeAll() +'">' +
'<span class="select2-selection__clear">' +
'&times;' +
'</span>'
);
Utils.StoreData($remove[0], 'data', data);
$remove.data('data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove);
};
@@ -1983,7 +1856,7 @@ S2.define('select2/selection/search',[
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
'</li>'
);
@@ -2000,18 +1873,14 @@ S2.define('select2/selection/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
container.on('open', function () {
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus');
});
container.on('close', function () {
self.$search.val('');
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus');
});
@@ -2031,11 +1900,7 @@ S2.define('select2/selection/search',[
});
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
self.$search.attr('aria-activedescendant', params.id);
});
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -2060,7 +1925,7 @@ S2.define('select2/selection/search',[
.prev('.select2-selection__choice');
if ($previousChoice.length > 0) {
var item = Utils.GetData($previousChoice[0], 'data');
var item = $previousChoice.data('data');
self.searchRemoveChoice(item);
@@ -2069,12 +1934,6 @@ S2.define('select2/selection/search',[
}
});
this.$selection.on('click', '.select2-search--inline', function (evt) {
if (self.$search.val()) {
evt.stopPropagation();
}
});
// Try to detect the IE version should the `documentMode` property that
// is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check.
@@ -2160,7 +2019,7 @@ S2.define('select2/selection/search',[
this.resizeSearch();
if (searchHadFocus) {
this.$search.trigger('focus');
this.$search.focus();
}
};
@@ -2193,7 +2052,7 @@ S2.define('select2/selection/search',[
var width = '';
if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.select2-selection__rendered').width();
width = this.$selection.find('.select2-selection__rendered').innerWidth();
} else {
var minimumWidth = this.$search.val().length + 1;
@@ -2217,13 +2076,10 @@ S2.define('select2/selection/eventRelay',[
'open', 'opening',
'close', 'closing',
'select', 'selecting',
'unselect', 'unselecting',
'clear', 'clearing'
'unselect', 'unselecting'
];
var preventableEvents = [
'opening', 'closing', 'selecting', 'unselecting', 'clearing'
];
var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
decorated.call(this, container, $container);
@@ -2556,7 +2412,6 @@ S2.define('select2/diacritics',[
'\u019F': 'O',
'\uA74A': 'O',
'\uA74C': 'O',
'\u0152': 'OE',
'\u01A2': 'OI',
'\uA74E': 'OO',
'\u0222': 'OU',
@@ -2966,7 +2821,6 @@ S2.define('select2/diacritics',[
'\uA74B': 'o',
'\uA74D': 'o',
'\u0275': 'o',
'\u0153': 'oe',
'\u01A3': 'oi',
'\u0223': 'ou',
'\uA74F': 'oo',
@@ -3135,9 +2989,8 @@ S2.define('select2/diacritics',[
'\u03CD': '\u03C5',
'\u03CB': '\u03C5',
'\u03B0': '\u03C5',
'\u03CE': '\u03C9',
'\u03C2': '\u03C3',
'\u2019': '\''
'\u03C9': '\u03C9',
'\u03C2': '\u03C3'
};
return diacritics;
@@ -3222,7 +3075,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) {
data.element.selected = true;
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
return;
}
@@ -3243,13 +3096,13 @@ S2.define('select2/data/select',[
}
self.$element.val(val);
self.$element.trigger('input').trigger('change');
self.$element.trigger('change');
});
} else {
var val = data.id;
this.$element.val(val);
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
}
};
@@ -3265,7 +3118,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) {
data.element.selected = false;
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
return;
}
@@ -3283,7 +3136,7 @@ S2.define('select2/data/select',[
self.$element.val(val);
self.$element.trigger('input').trigger('change');
self.$element.trigger('change');
});
};
@@ -3305,7 +3158,7 @@ S2.define('select2/data/select',[
// Remove anything added to child elements
this.$element.find('*').each(function () {
// Remove any custom data set by Select2
Utils.RemoveData(this);
$.removeData(this, 'data');
});
};
@@ -3378,7 +3231,7 @@ S2.define('select2/data/select',[
normalizedData.element = option;
// Override the option's data with the combined data
Utils.StoreData(option, 'data', normalizedData);
$.data(option, 'data', normalizedData);
return $option;
};
@@ -3386,7 +3239,7 @@ S2.define('select2/data/select',[
SelectAdapter.prototype.item = function ($option) {
var data = {};
data = Utils.GetData($option[0], 'data');
data = $.data($option[0], 'data');
if (data != null) {
return data;
@@ -3424,13 +3277,13 @@ S2.define('select2/data/select',[
data = this._normalizeItem(data);
data.element = $option[0];
Utils.StoreData($option[0], 'data', data);
$.data($option[0], 'data', data);
return data;
};
SelectAdapter.prototype._normalizeItem = function (item) {
if (item !== Object(item)) {
if (!$.isPlainObject(item)) {
item = {
id: item,
text: item
@@ -3476,19 +3329,15 @@ S2.define('select2/data/array',[
'jquery'
], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) {
this._dataToConvert = options.get('data') || [];
var data = options.get('data') || [];
ArrayAdapter.__super__.constructor.call(this, $element, options);
this.addOptions(this.convertToOptions(data));
}
Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.bind = function (container, $container) {
ArrayAdapter.__super__.bind.call(this, container, $container);
this.addOptions(this.convertToOptions(this._dataToConvert));
};
ArrayAdapter.prototype.select = function (data) {
var $option = this.$element.find('option').filter(function (i, elm) {
return elm.value == data.id.toString();
@@ -3638,8 +3487,7 @@ S2.define('select2/data/ajax',[
}, function () {
// Attempt to detect if a request was aborted
// Only works if the transport exposes a status property
if ('status' in $request &&
($request.status === 0 || $request.status === '0')) {
if ($request.status && $request.status === '0') {
return;
}
@@ -3778,6 +3626,8 @@ S2.define('select2/data/tags',[
};
Tags.prototype._removeOldTags = function (_) {
var tag = this._lastTag;
var $options = this.$element.find('option[data-select2-tag]');
$options.each(function () {
@@ -3852,7 +3702,7 @@ S2.define('select2/data/tokenizer',[
// Replace the search term if we have the search box
if (this.$search.length) {
this.$search.val(tokenData.term);
this.$search.trigger('focus');
this.$search.focus();
}
params.term = tokenData.term;
@@ -3981,30 +3831,10 @@ S2.define('select2/data/maximumSelectionLength',[
decorated.call(this, $e, options);
}
MaximumSelectionLength.prototype.bind =
function (decorated, container, $container) {
var self = this;
decorated.call(this, container, $container);
container.on('select', function () {
self._checkIfMaximumSelected();
});
};
MaximumSelectionLength.prototype.query =
function (decorated, params, callback) {
var self = this;
this._checkIfMaximumSelected(function () {
decorated.call(self, params, callback);
});
};
MaximumSelectionLength.prototype._checkIfMaximumSelected =
function (_, successCallback) {
var self = this;
this.current(function (currentData) {
var count = currentData != null ? currentData.length : 0;
if (self.maximumSelectionLength > 0 &&
@@ -4017,10 +3847,7 @@ S2.define('select2/data/maximumSelectionLength',[
});
return;
}
if (successCallback) {
successCallback();
}
decorated.call(self, params, callback);
});
};
@@ -4059,7 +3886,7 @@ S2.define('select2/dropdown',[
};
Dropdown.prototype.position = function ($dropdown, $container) {
// Should be implemented in subclasses
// Should be implmented in subclasses
};
Dropdown.prototype.destroy = function () {
@@ -4083,7 +3910,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
' spellcheck="false" role="textbox" />' +
'</span>'
);
@@ -4098,8 +3925,6 @@ S2.define('select2/dropdown/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
this.$search.on('keydown', function (evt) {
@@ -4122,27 +3947,23 @@ S2.define('select2/dropdown/search',[
container.on('open', function () {
self.$search.attr('tabindex', 0);
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus');
self.$search.focus();
window.setTimeout(function () {
self.$search.trigger('focus');
self.$search.focus();
}, 0);
});
container.on('close', function () {
self.$search.attr('tabindex', -1);
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.val('');
self.$search.trigger('blur');
});
container.on('focus', function () {
if (!container.isOpen()) {
self.$search.trigger('focus');
self.$search.focus();
}
});
@@ -4157,14 +3978,6 @@ S2.define('select2/dropdown/search',[
}
}
});
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
});
};
Search.prototype.handleSearch = function (evt) {
@@ -4249,7 +4062,6 @@ S2.define('select2/dropdown/infiniteScroll',[
if (this.showLoadingMore(data)) {
this.$results.append(this.$loadingMore);
this.loadMoreIfNeeded();
}
};
@@ -4268,27 +4080,25 @@ S2.define('select2/dropdown/infiniteScroll',[
self.loading = true;
});
this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
};
this.$results.on('scroll', function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
self.$loadingMore[0]
);
InfiniteScroll.prototype.loadMoreIfNeeded = function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
this.$loadingMore[0]
);
if (self.loading || !isLoadMoreVisible) {
return;
}
if (this.loading || !isLoadMoreVisible) {
return;
}
var currentOffset = self.$results.offset().top +
self.$results.outerHeight(false);
var loadingMoreOffset = self.$loadingMore.offset().top +
self.$loadingMore.outerHeight(false);
var currentOffset = this.$results.offset().top +
this.$results.outerHeight(false);
var loadingMoreOffset = this.$loadingMore.offset().top +
this.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) {
this.loadMore();
}
if (currentOffset + 50 >= loadingMoreOffset) {
self.loadMore();
}
});
};
InfiniteScroll.prototype.loadMore = function () {
@@ -4309,7 +4119,7 @@ S2.define('select2/dropdown/infiniteScroll',[
var $option = $(
'<li ' +
'class="select2-results__option select2-results__option--load-more"' +
'role="option" aria-disabled="true"></li>'
'role="treeitem" aria-disabled="true"></li>'
);
var message = this.options.get('translations').get('loadingMore');
@@ -4327,7 +4137,7 @@ S2.define('select2/dropdown/attachBody',[
'../utils'
], function ($, Utils) {
function AttachBody (decorated, $element, options) {
this.$dropdownParent = $(options.get('dropdownParent') || document.body);
this.$dropdownParent = options.get('dropdownParent') || $(document.body);
decorated.call(this, $element, options);
}
@@ -4335,14 +4145,27 @@ S2.define('select2/dropdown/attachBody',[
AttachBody.prototype.bind = function (decorated, container, $container) {
var self = this;
var setupResultsEvents = false;
decorated.call(this, container, $container);
container.on('open', function () {
self._showDropdown();
self._attachPositioningHandler(container);
// Must bind after the results handlers to ensure correct sizing
self._bindContainerResultHandlers(container);
if (!setupResultsEvents) {
setupResultsEvents = true;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
}
});
container.on('close', function () {
@@ -4391,44 +4214,6 @@ S2.define('select2/dropdown/attachBody',[
this.$dropdownContainer.detach();
};
AttachBody.prototype._bindContainerResultHandlers =
function (decorated, container) {
// These should only be bound once
if (this._containerResultsHandlersBound) {
return;
}
var self = this;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:message', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('select', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('unselect', function () {
self._positionDropdown();
self._resizeDropdown();
});
this._containerResultsHandlersBound = true;
};
AttachBody.prototype._attachPositioningHandler =
function (decorated, container) {
var self = this;
@@ -4439,14 +4224,14 @@ S2.define('select2/dropdown/attachBody',[
var $watchers = this.$container.parents().filter(Utils.hasScroll);
$watchers.each(function () {
Utils.StoreData(this, 'select2-scroll-position', {
$(this).data('select2-scroll-position', {
x: $(this).scrollLeft(),
y: $(this).scrollTop()
});
});
$watchers.on(scrollEvent, function (ev) {
var position = Utils.GetData(this, 'select2-scroll-position');
var position = $(this).data('select2-scroll-position');
$(this).scrollTop(position.y);
});
@@ -4505,26 +4290,16 @@ S2.define('select2/dropdown/attachBody',[
top: container.bottom
};
// Determine what the parent element is to use for calculating the offset
// Determine what the parent element is to use for calciulating the offset
var $offsetParent = this.$dropdownParent;
// For statically positioned elements, we need to get the element
// For statically positoned elements, we need to get the element
// that is determining the offset
if ($offsetParent.css('position') === 'static') {
$offsetParent = $offsetParent.offsetParent();
}
var parentOffset = {
top: 0,
left: 0
};
if (
$.contains(document.body, $offsetParent[0]) ||
$offsetParent[0].isConnected
) {
parentOffset = $offsetParent.offset();
}
var parentOffset = $offsetParent.offset();
css.top -= parentOffset.top;
css.left -= parentOffset.left;
@@ -4621,8 +4396,8 @@ S2.define('select2/dropdown/minimumResultsForSearch',[
});
S2.define('select2/dropdown/selectOnClose',[
'../utils'
], function (Utils) {
], function () {
function SelectOnClose () { }
SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -4653,7 +4428,7 @@ S2.define('select2/dropdown/selectOnClose',[
return;
}
var data = Utils.GetData($highlightedResults[0], 'data');
var data = $highlightedResults.data('data');
// Don't re-select already selected resulte
if (
@@ -4694,7 +4469,7 @@ S2.define('select2/dropdown/closeOnSelect',[
var originalEvent = evt.originalEvent;
// Don't close if the control key is being held
if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
if (originalEvent && originalEvent.ctrlKey) {
return;
}
@@ -4748,9 +4523,6 @@ S2.define('select2/i18n/en',[],function () {
},
searching: function () {
return 'Searching…';
},
removeAllItems: function () {
return 'Remove all items';
}
};
});
@@ -4989,29 +4761,66 @@ S2.define('select2/defaults',[
);
}
// If the defaults were not previously applied from an element, it is
// possible for the language option to have not been resolved
options.language = this._resolveLanguage(options.language);
if (typeof options.language === 'string') {
// Check if the language is specified with a region
if (options.language.indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = options.language.split('-');
var baseLanguage = languageParts[0];
// Always fall back to English since it will always be complete
options.language.push('en');
var uniqueLanguages = [];
for (var l = 0; l < options.language.length; l++) {
var language = options.language[l];
if (uniqueLanguages.indexOf(language) === -1) {
uniqueLanguages.push(language);
options.language = [options.language, baseLanguage];
} else {
options.language = [options.language];
}
}
options.language = uniqueLanguages;
if ($.isArray(options.language)) {
var languages = new Translation();
options.language.push('en');
options.translations = this._processTranslations(
options.language,
options.debug
);
var languageNames = options.language;
for (var l = 0; l < languageNames.length; l++) {
var name = languageNames[l];
var language = {};
try {
// Try to load it with the original name
language = Translation.loadPath(name);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
name = this.defaults.amdLanguageBase + name;
language = Translation.loadPath(name);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files.
if (options.debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + name + '" could not be ' +
'automatically loaded. A fallback will be used instead.'
);
}
continue;
}
}
languages.extend(language);
}
options.translations = languages;
} else {
var baseTranslation = Translation.loadPath(
this.defaults.amdLanguageBase + 'en'
);
var customTranslation = new Translation(options.language);
customTranslation.extend(baseTranslation);
options.translations = customTranslation;
}
return options;
};
@@ -5078,14 +4887,13 @@ S2.define('select2/defaults',[
debug: false,
dropdownAutoWidth: false,
escapeMarkup: Utils.escapeMarkup,
language: {},
language: EnglishTranslation,
matcher: matcher,
minimumInputLength: 0,
maximumInputLength: 0,
maximumSelectionLength: 0,
minimumResultsForSearch: 0,
selectOnClose: false,
scrollAfterSelect: false,
sorter: function (data) {
return data;
},
@@ -5100,103 +4908,6 @@ S2.define('select2/defaults',[
};
};
Defaults.prototype.applyFromElement = function (options, $element) {
var optionLanguage = options.language;
var defaultLanguage = this.defaults.language;
var elementLanguage = $element.prop('lang');
var parentLanguage = $element.closest('[lang]').prop('lang');
var languages = Array.prototype.concat.call(
this._resolveLanguage(elementLanguage),
this._resolveLanguage(optionLanguage),
this._resolveLanguage(defaultLanguage),
this._resolveLanguage(parentLanguage)
);
options.language = languages;
return options;
};
Defaults.prototype._resolveLanguage = function (language) {
if (!language) {
return [];
}
if ($.isEmptyObject(language)) {
return [];
}
if ($.isPlainObject(language)) {
return [language];
}
var languages;
if (!$.isArray(language)) {
languages = [language];
} else {
languages = language;
}
var resolvedLanguages = [];
for (var l = 0; l < languages.length; l++) {
resolvedLanguages.push(languages[l]);
if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = languages[l].split('-');
var baseLanguage = languageParts[0];
resolvedLanguages.push(baseLanguage);
}
}
return resolvedLanguages;
};
Defaults.prototype._processTranslations = function (languages, debug) {
var translations = new Translation();
for (var l = 0; l < languages.length; l++) {
var languageData = new Translation();
var language = languages[l];
if (typeof language === 'string') {
try {
// Try to load it with the original name
languageData = Translation.loadPath(language);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
language = this.defaults.amdLanguageBase + language;
languageData = Translation.loadPath(language);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files
if (debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + language + '" could ' +
'not be automatically loaded. A fallback will be used instead.'
);
}
}
}
} else if ($.isPlainObject(language)) {
languageData = new Translation(language);
} else {
languageData = language;
}
translations.extend(languageData);
}
return translations;
};
Defaults.prototype.set = function (key, value) {
var camelKey = $.camelCase(key);
@@ -5205,7 +4916,7 @@ S2.define('select2/defaults',[
var convertedData = Utils._convertData(data);
$.extend(true, this.defaults, convertedData);
$.extend(this.defaults, convertedData);
};
var defaults = new Defaults();
@@ -5226,10 +4937,6 @@ S2.define('select2/options',[
this.fromElement($element);
}
if ($element != null) {
this.options = Defaults.applyFromElement(this.options, $element);
}
this.options = Defaults.apply(this.options);
if ($element && $element.is('input')) {
@@ -5253,6 +4960,14 @@ S2.define('select2/options',[
this.options.disabled = $e.prop('disabled');
}
if (this.options.language == null) {
if ($e.prop('lang')) {
this.options.language = $e.prop('lang').toLowerCase();
} else if ($e.closest('[lang]').prop('lang')) {
this.options.language = $e.closest('[lang]').prop('lang');
}
}
if (this.options.dir == null) {
if ($e.prop('dir')) {
this.options.dir = $e.prop('dir');
@@ -5266,7 +4981,7 @@ S2.define('select2/options',[
$e.prop('disabled', this.options.disabled);
$e.prop('multiple', this.options.multiple);
if (Utils.GetData($e[0], 'select2Tags')) {
if ($e.data('select2Tags')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -5275,11 +4990,11 @@ S2.define('select2/options',[
);
}
Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
Utils.StoreData($e[0], 'tags', true);
$e.data('data', $e.data('select2Tags'));
$e.data('tags', true);
}
if (Utils.GetData($e[0], 'ajaxUrl')) {
if ($e.data('ajaxUrl')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'Select2: The `data-ajax-url` attribute has been changed to ' +
@@ -5288,45 +5003,21 @@ S2.define('select2/options',[
);
}
$e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
$e.attr('ajax--url', $e.data('ajaxUrl'));
$e.data('ajax--url', $e.data('ajaxUrl'));
}
var dataset = {};
function upperCaseLetter(_, letter) {
return letter.toUpperCase();
}
// Pre-load all of the attributes which are prefixed with `data-`
for (var attr = 0; attr < $e[0].attributes.length; attr++) {
var attributeName = $e[0].attributes[attr].name;
var prefix = 'data-';
if (attributeName.substr(0, prefix.length) == prefix) {
// Get the contents of the attribute after `data-`
var dataName = attributeName.substring(prefix.length);
// Get the data contents from the consistent source
// This is more than likely the jQuery data helper
var dataValue = Utils.GetData($e[0], dataName);
// camelCase the attribute name to match the spec
var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
// Store the data attribute contents into the dataset since
dataset[camelDataName] = dataValue;
}
}
// Prefer the element's `dataset` attribute if it exists
// jQuery 1.x does not correctly handle data attributes with multiple dashes
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
dataset = $.extend(true, {}, $e[0].dataset, dataset);
dataset = $.extend(true, {}, $e[0].dataset, $e.data());
} else {
dataset = $e.data();
}
// Prefer our internal data cache if it exists
var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
var data = $.extend(true, {}, dataset);
data = Utils._convertData(data);
@@ -5363,8 +5054,8 @@ S2.define('select2/core',[
'./keys'
], function ($, Options, Utils, KEYS) {
var Select2 = function ($element, options) {
if (Utils.GetData($element[0], 'select2') != null) {
Utils.GetData($element[0], 'select2').destroy();
if ($element.data('select2') != null) {
$element.data('select2').destroy();
}
this.$element = $element;
@@ -5380,7 +5071,7 @@ S2.define('select2/core',[
// Set up the tabindex
var tabindex = $element.attr('tabindex') || 0;
Utils.StoreData($element[0], 'old-tabindex', tabindex);
$element.data('old-tabindex', tabindex);
$element.attr('tabindex', '-1');
// Set up containers and adapters
@@ -5441,9 +5132,6 @@ S2.define('select2/core',[
// Synchronize any monitored attributes
this._syncAttributes();
Utils.StoreData($element[0], 'select2', this);
// Ensure backwards compatibility with $element.data('select2').
$element.data('select2', this);
};
@@ -5520,12 +5208,6 @@ S2.define('select2/core',[
return null;
}
if (method == 'computedstyle') {
var computedStyle = window.getComputedStyle($element[0]);
return computedStyle.width;
}
return method;
};
@@ -5566,8 +5248,8 @@ S2.define('select2/core',[
if (observer != null) {
this._observer = new observer(function (mutations) {
self._syncA();
self._syncS(null, mutations);
$.each(mutations, self._syncA);
$.each(mutations, self._syncS);
});
this._observer.observe(this.$element[0], {
attributes: true,
@@ -5689,7 +5371,7 @@ S2.define('select2/core',[
if (self.isOpen()) {
if (key === KEYS.ESC || key === KEYS.TAB ||
(key === KEYS.UP && evt.altKey)) {
self.close(evt);
self.close();
evt.preventDefault();
} else if (key === KEYS.ENTER) {
@@ -5723,7 +5405,7 @@ S2.define('select2/core',[
Select2.prototype._syncAttributes = function () {
this.options.set('disabled', this.$element.prop('disabled'));
if (this.isDisabled()) {
if (this.options.get('disabled')) {
if (this.isOpen()) {
this.close();
}
@@ -5734,7 +5416,7 @@ S2.define('select2/core',[
}
};
Select2.prototype._isChangeMutation = function (evt, mutations) {
Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = false;
var self = this;
@@ -5762,22 +5444,7 @@ S2.define('select2/core',[
}
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
changed = true;
} else if ($.isArray(mutations)) {
$.each(mutations, function(evt, mutation) {
if (self._isChangeMutation(evt, mutation)) {
// We've found a change mutation.
// Let's escape from the loop and continue
changed = true;
return false;
}
});
}
return changed;
};
Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = this._isChangeMutation(evt, mutations);
var self = this;
// Only re-pull the data if we think there is a change
if (changed) {
@@ -5799,8 +5466,7 @@ S2.define('select2/core',[
'open': 'opening',
'close': 'closing',
'select': 'selecting',
'unselect': 'unselecting',
'clear': 'clearing'
'unselect': 'unselecting'
};
if (args === undefined) {
@@ -5828,7 +5494,7 @@ S2.define('select2/core',[
};
Select2.prototype.toggleDropdown = function () {
if (this.isDisabled()) {
if (this.options.get('disabled')) {
return;
}
@@ -5844,40 +5510,15 @@ S2.define('select2/core',[
return;
}
if (this.isDisabled()) {
return;
}
this.trigger('query', {});
};
Select2.prototype.close = function (evt) {
Select2.prototype.close = function () {
if (!this.isOpen()) {
return;
}
this.trigger('close', { originalEvent : evt });
};
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
Select2.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
Select2.prototype.isDisabled = function () {
return this.options.get('disabled');
this.trigger('close', {});
};
Select2.prototype.isOpen = function () {
@@ -5954,7 +5595,7 @@ S2.define('select2/core',[
});
}
this.$element.val(newVal).trigger('input').trigger('change');
this.$element.val(newVal).trigger('change');
};
Select2.prototype.destroy = function () {
@@ -5980,12 +5621,10 @@ S2.define('select2/core',[
this._syncS = null;
this.$element.off('.select2');
this.$element.attr('tabindex',
Utils.GetData(this.$element[0], 'old-tabindex'));
this.$element.attr('tabindex', this.$element.data('old-tabindex'));
this.$element.removeClass('select2-hidden-accessible');
this.$element.attr('aria-hidden', 'false');
Utils.RemoveData(this.$element[0]);
this.$element.removeData('select2');
this.dataAdapter.destroy();
@@ -6013,7 +5652,7 @@ S2.define('select2/core',[
this.$container.addClass('select2-container--' + this.options.get('theme'));
Utils.StoreData($container[0], 'element', this.$element);
$container.data('element', this.$element);
return $container;
};
@@ -6223,9 +5862,8 @@ S2.define('select2/compat/initSelection',[
});
S2.define('select2/compat/inputData',[
'jquery',
'../utils'
], function ($, Utils) {
'jquery'
], function ($) {
function InputData (decorated, $element, options) {
this._currentData = [];
this._valueSeparator = options.get('valueSeparator') || ',';
@@ -6289,13 +5927,13 @@ S2.define('select2/compat/inputData',[
});
this.$element.val(data.id);
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
} else {
var value = this.$element.val();
value += this._valueSeparator + data.id;
this.$element.val(value);
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
}
};
@@ -6318,7 +5956,7 @@ S2.define('select2/compat/inputData',[
}
self.$element.val(values.join(self._valueSeparator));
self.$element.trigger('input').trigger('change');
self.$element.trigger('change');
});
};
@@ -6342,7 +5980,7 @@ S2.define('select2/compat/inputData',[
InputData.prototype.addOptions = function (_, $options) {
var options = $.map($options, function ($option) {
return Utils.GetData($option[0], 'data');
return $.data($option[0], 'data');
});
this._currentData.push.apply(this._currentData, options);
@@ -6745,9 +6383,8 @@ S2.define('jquery.select2',[
'jquery-mousewheel',
'./select2/core',
'./select2/defaults',
'./select2/utils'
], function ($, _, Select2, Defaults, Utils) {
'./select2/defaults'
], function ($, _, Select2, Defaults) {
if ($.fn.select2 == null) {
// All methods that should return the element
var thisMethods = ['open', 'close', 'destroy'];
@@ -6768,7 +6405,7 @@ S2.define('jquery.select2',[
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = Utils.GetData(this, 'select2');
var instance = $(this).data('select2');
if (instance == null && window.console && console.error) {
console.error(
+1 -2
View File
File diff suppressed because one or more lines are too long
+214 -576
View File
@@ -1,11 +1,11 @@
/*!
* Select2 4.0.13
* Select2 4.0.5
* https://select2.github.io
*
* Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md
*/
;(function (factory) {
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
@@ -574,10 +574,10 @@ S2.define('select2/utils',[
DecoratedClass.prototype = new ctr();
for (var m = 0; m < superMethods.length; m++) {
var superMethod = superMethods[m];
var superMethod = superMethods[m];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
}
var calledMethod = function (methodName) {
@@ -772,70 +772,6 @@ S2.define('select2/utils',[
$element.append($nodes);
};
// Cache objects in Utils.__cache instead of $.data (see #4346)
Utils.__cache = {};
var id = 0;
Utils.GetUniqueElementId = function (element) {
// Get a unique element Id. If element has no id,
// creates a new unique number, stores it in the id
// attribute and returns the new id.
// If an id already exists, it simply returns it.
var select2Id = element.getAttribute('data-select2-id');
if (select2Id == null) {
// If element has id, use it.
if (element.id) {
select2Id = element.id;
element.setAttribute('data-select2-id', select2Id);
} else {
element.setAttribute('data-select2-id', ++id);
select2Id = id.toString();
}
}
return select2Id;
};
Utils.StoreData = function (element, name, value) {
// Stores an item in the cache for a specified element.
// name is the cache key.
var id = Utils.GetUniqueElementId(element);
if (!Utils.__cache[id]) {
Utils.__cache[id] = {};
}
Utils.__cache[id][name] = value;
};
Utils.GetData = function (element, name) {
// Retrieves a value from the cache by its key (name)
// name is optional. If no name specified, return
// all cache items for the specified element.
// and for a specified element.
var id = Utils.GetUniqueElementId(element);
if (name) {
if (Utils.__cache[id]) {
if (Utils.__cache[id][name] != null) {
return Utils.__cache[id][name];
}
return $(element).data(name); // Fallback to HTML5 data attribs.
}
return $(element).data(name); // Fallback to HTML5 data attribs.
} else {
return Utils.__cache[id];
}
};
Utils.RemoveData = function (element) {
// Removes all cached items for a specified element.
var id = Utils.GetUniqueElementId(element);
if (Utils.__cache[id] != null) {
delete Utils.__cache[id];
}
element.removeAttribute('data-select2-id');
};
return Utils;
});
@@ -855,7 +791,7 @@ S2.define('select2/results',[
Results.prototype.render = function () {
var $results = $(
'<ul class="select2-results__options" role="listbox"></ul>'
'<ul class="select2-results__options" role="tree"></ul>'
);
if (this.options.get('multiple')) {
@@ -878,7 +814,7 @@ S2.define('select2/results',[
this.hideLoading();
var $message = $(
'<li role="alert" aria-live="assertive"' +
'<li role="treeitem" aria-live="assertive"' +
' class="select2-results__option"></li>'
);
@@ -971,7 +907,7 @@ S2.define('select2/results',[
$options.each(function () {
var $option = $(this);
var item = Utils.GetData(this, 'data');
var item = $.data(this, 'data');
// id needs to be converted to a string when comparing
var id = '' + item.id;
@@ -1012,16 +948,11 @@ S2.define('select2/results',[
option.className = 'select2-results__option';
var attrs = {
'role': 'option',
'role': 'treeitem',
'aria-selected': 'false'
};
var matches = window.Element.prototype.matches ||
window.Element.prototype.msMatchesSelector ||
window.Element.prototype.webkitMatchesSelector;
if ((data.element != null && matches.call(data.element, ':disabled')) ||
(data.element == null && data.disabled)) {
if (data.disabled) {
delete attrs['aria-selected'];
attrs['aria-disabled'] = 'true';
}
@@ -1081,7 +1012,7 @@ S2.define('select2/results',[
this.template(data, option);
}
Utils.StoreData(option, 'data', data);
$.data(option, 'data', data);
return option;
};
@@ -1122,10 +1053,7 @@ S2.define('select2/results',[
}
self.setClasses();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
self.highlightFirstItem();
});
container.on('unselect', function () {
@@ -1134,10 +1062,7 @@ S2.define('select2/results',[
}
self.setClasses();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
self.highlightFirstItem();
});
container.on('open', function () {
@@ -1173,7 +1098,7 @@ S2.define('select2/results',[
return;
}
var data = Utils.GetData($highlighted[0], 'data');
var data = $highlighted.data('data');
if ($highlighted.attr('aria-selected') == 'true') {
self.trigger('close', {});
@@ -1191,9 +1116,8 @@ S2.define('select2/results',[
var currentIndex = $options.index($highlighted);
// If we are already at the top, don't move further
// If no options, currentIndex will be -1
if (currentIndex <= 0) {
// If we are already at te top, don't move further
if (currentIndex === 0) {
return;
}
@@ -1286,7 +1210,7 @@ S2.define('select2/results',[
function (evt) {
var $this = $(this);
var data = Utils.GetData(this, 'data');
var data = $this.data('data');
if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) {
@@ -1309,7 +1233,7 @@ S2.define('select2/results',[
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
function (evt) {
var data = Utils.GetData(this, 'data');
var data = $(this).data('data');
self.getHighlightedResults()
.removeClass('select2-results__option--highlighted');
@@ -1424,15 +1348,14 @@ S2.define('select2/selection/base',[
this._tabindex = 0;
if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
if (this.$element.data('old-tabindex') != null) {
this._tabindex = this.$element.data('old-tabindex');
} else if (this.$element.attr('tabindex') != null) {
this._tabindex = this.$element.attr('tabindex');
}
$selection.attr('title', this.$element.attr('title'));
$selection.attr('tabindex', this._tabindex);
$selection.attr('aria-disabled', 'false');
this.$selection = $selection;
@@ -1442,6 +1365,7 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.bind = function (container, $container) {
var self = this;
var id = container.id + '-container';
var resultsId = container.id + '-results';
this.container = container;
@@ -1484,19 +1408,17 @@ S2.define('select2/selection/base',[
self.$selection.removeAttr('aria-activedescendant');
self.$selection.removeAttr('aria-owns');
self.$selection.trigger('focus');
self.$selection.focus();
self._detachCloseHandler(container);
});
container.on('enable', function () {
self.$selection.attr('tabindex', self._tabindex);
self.$selection.attr('aria-disabled', 'false');
});
container.on('disable', function () {
self.$selection.attr('tabindex', '-1');
self.$selection.attr('aria-disabled', 'true');
});
};
@@ -1519,6 +1441,7 @@ S2.define('select2/selection/base',[
};
BaseSelection.prototype._attachCloseHandler = function (container) {
var self = this;
$(document.body).on('mousedown.select2.' + container.id, function (e) {
var $target = $(e.target);
@@ -1528,11 +1451,13 @@ S2.define('select2/selection/base',[
var $all = $('.select2.select2-container--open');
$all.each(function () {
var $this = $(this);
if (this == $select[0]) {
return;
}
var $element = Utils.GetData(this, 'element');
var $element = $this.data('element');
$element.select2('close');
});
@@ -1556,27 +1481,6 @@ S2.define('select2/selection/base',[
throw new Error('The `update` method must be defined in child classes.');
};
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
BaseSelection.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
BaseSelection.prototype.isDisabled = function () {
return this.options.get('disabled');
};
return BaseSelection;
});
@@ -1614,10 +1518,7 @@ S2.define('select2/selection/single',[
var id = container.id + '-container';
this.$selection.find('.select2-selection__rendered')
.attr('id', id)
.attr('role', 'textbox')
.attr('aria-readonly', 'true');
this.$selection.find('.select2-selection__rendered').attr('id', id);
this.$selection.attr('aria-labelledby', id);
this.$selection.on('mousedown', function (evt) {
@@ -1641,15 +1542,17 @@ S2.define('select2/selection/single',[
container.on('focus', function (evt) {
if (!container.isOpen()) {
self.$selection.trigger('focus');
self.$selection.focus();
}
});
container.on('selection:update', function (params) {
self.update(params.data);
});
};
SingleSelection.prototype.clear = function () {
var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title'); // clear tooltip on empty
this.$selection.find('.select2-selection__rendered').empty();
};
SingleSelection.prototype.display = function (data, container) {
@@ -1675,14 +1578,7 @@ S2.define('select2/selection/single',[
var formatted = this.display(selection, $rendered);
$rendered.empty().append(formatted);
var title = selection.title || selection.text;
if (title) {
$rendered.attr('title', title);
} else {
$rendered.removeAttr('title');
}
$rendered.prop('title', selection.title || selection.text);
};
return SingleSelection;
@@ -1727,14 +1623,14 @@ S2.define('select2/selection/multiple',[
'.select2-selection__choice__remove',
function (evt) {
// Ignore the event if it is disabled
if (self.isDisabled()) {
if (self.options.get('disabled')) {
return;
}
var $remove = $(this);
var $selection = $remove.parent();
var data = Utils.GetData($selection[0], 'data');
var data = $selection.data('data');
self.trigger('unselect', {
originalEvent: evt,
@@ -1745,9 +1641,7 @@ S2.define('select2/selection/multiple',[
};
MultipleSelection.prototype.clear = function () {
var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title');
this.$selection.find('.select2-selection__rendered').empty();
};
MultipleSelection.prototype.display = function (data, container) {
@@ -1785,14 +1679,9 @@ S2.define('select2/selection/multiple',[
var formatted = this.display(selection, $selection);
$selection.append(formatted);
$selection.prop('title', selection.title || selection.text);
var title = selection.title || selection.text;
if (title) {
$selection.attr('title', title);
}
Utils.StoreData($selection[0], 'data', selection);
$selection.data('data', selection);
$selections.push($selection);
}
@@ -1857,9 +1746,8 @@ S2.define('select2/selection/placeholder',[
S2.define('select2/selection/allowClear',[
'jquery',
'../keys',
'../utils'
], function ($, KEYS, Utils) {
'../keys'
], function ($, KEYS) {
function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -1888,7 +1776,7 @@ S2.define('select2/selection/allowClear',[
AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled
if (this.isDisabled()) {
if (this.options.get('disabled')) {
return;
}
@@ -1901,22 +1789,10 @@ S2.define('select2/selection/allowClear',[
evt.stopPropagation();
var data = Utils.GetData($clear[0], 'data');
var previousVal = this.$element.val();
this.$element.val(this.placeholder.id);
var unselectData = {
data: data
};
this.trigger('clear', unselectData);
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
var data = $clear.data('data');
for (var d = 0; d < data.length; d++) {
unselectData = {
var unselectData = {
data: data[d]
};
@@ -1926,12 +1802,11 @@ S2.define('select2/selection/allowClear',[
// If the event was prevented, don't clear it out.
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
}
this.$element.trigger('input').trigger('change');
this.$element.val(this.placeholder.id).trigger('change');
this.trigger('toggle', {});
};
@@ -1954,14 +1829,12 @@ S2.define('select2/selection/allowClear',[
return;
}
var removeAll = this.options.get('translations').get('removeAllItems');
var $remove = $(
'<span class="select2-selection__clear" title="' + removeAll() +'">' +
'<span class="select2-selection__clear">' +
'&times;' +
'</span>'
);
Utils.StoreData($remove[0], 'data', data);
$remove.data('data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove);
};
@@ -1983,7 +1856,7 @@ S2.define('select2/selection/search',[
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
'</li>'
);
@@ -2000,18 +1873,14 @@ S2.define('select2/selection/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
container.on('open', function () {
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus');
});
container.on('close', function () {
self.$search.val('');
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus');
});
@@ -2031,11 +1900,7 @@ S2.define('select2/selection/search',[
});
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
self.$search.attr('aria-activedescendant', params.id);
});
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -2060,7 +1925,7 @@ S2.define('select2/selection/search',[
.prev('.select2-selection__choice');
if ($previousChoice.length > 0) {
var item = Utils.GetData($previousChoice[0], 'data');
var item = $previousChoice.data('data');
self.searchRemoveChoice(item);
@@ -2069,12 +1934,6 @@ S2.define('select2/selection/search',[
}
});
this.$selection.on('click', '.select2-search--inline', function (evt) {
if (self.$search.val()) {
evt.stopPropagation();
}
});
// Try to detect the IE version should the `documentMode` property that
// is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check.
@@ -2160,7 +2019,7 @@ S2.define('select2/selection/search',[
this.resizeSearch();
if (searchHadFocus) {
this.$search.trigger('focus');
this.$search.focus();
}
};
@@ -2193,7 +2052,7 @@ S2.define('select2/selection/search',[
var width = '';
if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.select2-selection__rendered').width();
width = this.$selection.find('.select2-selection__rendered').innerWidth();
} else {
var minimumWidth = this.$search.val().length + 1;
@@ -2217,13 +2076,10 @@ S2.define('select2/selection/eventRelay',[
'open', 'opening',
'close', 'closing',
'select', 'selecting',
'unselect', 'unselecting',
'clear', 'clearing'
'unselect', 'unselecting'
];
var preventableEvents = [
'opening', 'closing', 'selecting', 'unselecting', 'clearing'
];
var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
decorated.call(this, container, $container);
@@ -2556,7 +2412,6 @@ S2.define('select2/diacritics',[
'\u019F': 'O',
'\uA74A': 'O',
'\uA74C': 'O',
'\u0152': 'OE',
'\u01A2': 'OI',
'\uA74E': 'OO',
'\u0222': 'OU',
@@ -2966,7 +2821,6 @@ S2.define('select2/diacritics',[
'\uA74B': 'o',
'\uA74D': 'o',
'\u0275': 'o',
'\u0153': 'oe',
'\u01A3': 'oi',
'\u0223': 'ou',
'\uA74F': 'oo',
@@ -3135,9 +2989,8 @@ S2.define('select2/diacritics',[
'\u03CD': '\u03C5',
'\u03CB': '\u03C5',
'\u03B0': '\u03C5',
'\u03CE': '\u03C9',
'\u03C2': '\u03C3',
'\u2019': '\''
'\u03C9': '\u03C9',
'\u03C2': '\u03C3'
};
return diacritics;
@@ -3222,7 +3075,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) {
data.element.selected = true;
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
return;
}
@@ -3243,13 +3096,13 @@ S2.define('select2/data/select',[
}
self.$element.val(val);
self.$element.trigger('input').trigger('change');
self.$element.trigger('change');
});
} else {
var val = data.id;
this.$element.val(val);
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
}
};
@@ -3265,7 +3118,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) {
data.element.selected = false;
this.$element.trigger('input').trigger('change');
this.$element.trigger('change');
return;
}
@@ -3283,7 +3136,7 @@ S2.define('select2/data/select',[
self.$element.val(val);
self.$element.trigger('input').trigger('change');
self.$element.trigger('change');
});
};
@@ -3305,7 +3158,7 @@ S2.define('select2/data/select',[
// Remove anything added to child elements
this.$element.find('*').each(function () {
// Remove any custom data set by Select2
Utils.RemoveData(this);
$.removeData(this, 'data');
});
};
@@ -3378,7 +3231,7 @@ S2.define('select2/data/select',[
normalizedData.element = option;
// Override the option's data with the combined data
Utils.StoreData(option, 'data', normalizedData);
$.data(option, 'data', normalizedData);
return $option;
};
@@ -3386,7 +3239,7 @@ S2.define('select2/data/select',[
SelectAdapter.prototype.item = function ($option) {
var data = {};
data = Utils.GetData($option[0], 'data');
data = $.data($option[0], 'data');
if (data != null) {
return data;
@@ -3424,13 +3277,13 @@ S2.define('select2/data/select',[
data = this._normalizeItem(data);
data.element = $option[0];
Utils.StoreData($option[0], 'data', data);
$.data($option[0], 'data', data);
return data;
};
SelectAdapter.prototype._normalizeItem = function (item) {
if (item !== Object(item)) {
if (!$.isPlainObject(item)) {
item = {
id: item,
text: item
@@ -3476,19 +3329,15 @@ S2.define('select2/data/array',[
'jquery'
], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) {
this._dataToConvert = options.get('data') || [];
var data = options.get('data') || [];
ArrayAdapter.__super__.constructor.call(this, $element, options);
this.addOptions(this.convertToOptions(data));
}
Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.bind = function (container, $container) {
ArrayAdapter.__super__.bind.call(this, container, $container);
this.addOptions(this.convertToOptions(this._dataToConvert));
};
ArrayAdapter.prototype.select = function (data) {
var $option = this.$element.find('option').filter(function (i, elm) {
return elm.value == data.id.toString();
@@ -3638,8 +3487,7 @@ S2.define('select2/data/ajax',[
}, function () {
// Attempt to detect if a request was aborted
// Only works if the transport exposes a status property
if ('status' in $request &&
($request.status === 0 || $request.status === '0')) {
if ($request.status && $request.status === '0') {
return;
}
@@ -3778,6 +3626,8 @@ S2.define('select2/data/tags',[
};
Tags.prototype._removeOldTags = function (_) {
var tag = this._lastTag;
var $options = this.$element.find('option[data-select2-tag]');
$options.each(function () {
@@ -3852,7 +3702,7 @@ S2.define('select2/data/tokenizer',[
// Replace the search term if we have the search box
if (this.$search.length) {
this.$search.val(tokenData.term);
this.$search.trigger('focus');
this.$search.focus();
}
params.term = tokenData.term;
@@ -3981,30 +3831,10 @@ S2.define('select2/data/maximumSelectionLength',[
decorated.call(this, $e, options);
}
MaximumSelectionLength.prototype.bind =
function (decorated, container, $container) {
var self = this;
decorated.call(this, container, $container);
container.on('select', function () {
self._checkIfMaximumSelected();
});
};
MaximumSelectionLength.prototype.query =
function (decorated, params, callback) {
var self = this;
this._checkIfMaximumSelected(function () {
decorated.call(self, params, callback);
});
};
MaximumSelectionLength.prototype._checkIfMaximumSelected =
function (_, successCallback) {
var self = this;
this.current(function (currentData) {
var count = currentData != null ? currentData.length : 0;
if (self.maximumSelectionLength > 0 &&
@@ -4017,10 +3847,7 @@ S2.define('select2/data/maximumSelectionLength',[
});
return;
}
if (successCallback) {
successCallback();
}
decorated.call(self, params, callback);
});
};
@@ -4059,7 +3886,7 @@ S2.define('select2/dropdown',[
};
Dropdown.prototype.position = function ($dropdown, $container) {
// Should be implemented in subclasses
// Should be implmented in subclasses
};
Dropdown.prototype.destroy = function () {
@@ -4083,7 +3910,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
' spellcheck="false" role="textbox" />' +
'</span>'
);
@@ -4098,8 +3925,6 @@ S2.define('select2/dropdown/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
this.$search.on('keydown', function (evt) {
@@ -4122,27 +3947,23 @@ S2.define('select2/dropdown/search',[
container.on('open', function () {
self.$search.attr('tabindex', 0);
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus');
self.$search.focus();
window.setTimeout(function () {
self.$search.trigger('focus');
self.$search.focus();
}, 0);
});
container.on('close', function () {
self.$search.attr('tabindex', -1);
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.val('');
self.$search.trigger('blur');
});
container.on('focus', function () {
if (!container.isOpen()) {
self.$search.trigger('focus');
self.$search.focus();
}
});
@@ -4157,14 +3978,6 @@ S2.define('select2/dropdown/search',[
}
}
});
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
});
};
Search.prototype.handleSearch = function (evt) {
@@ -4249,7 +4062,6 @@ S2.define('select2/dropdown/infiniteScroll',[
if (this.showLoadingMore(data)) {
this.$results.append(this.$loadingMore);
this.loadMoreIfNeeded();
}
};
@@ -4268,27 +4080,25 @@ S2.define('select2/dropdown/infiniteScroll',[
self.loading = true;
});
this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
};
this.$results.on('scroll', function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
self.$loadingMore[0]
);
InfiniteScroll.prototype.loadMoreIfNeeded = function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
this.$loadingMore[0]
);
if (self.loading || !isLoadMoreVisible) {
return;
}
if (this.loading || !isLoadMoreVisible) {
return;
}
var currentOffset = self.$results.offset().top +
self.$results.outerHeight(false);
var loadingMoreOffset = self.$loadingMore.offset().top +
self.$loadingMore.outerHeight(false);
var currentOffset = this.$results.offset().top +
this.$results.outerHeight(false);
var loadingMoreOffset = this.$loadingMore.offset().top +
this.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) {
this.loadMore();
}
if (currentOffset + 50 >= loadingMoreOffset) {
self.loadMore();
}
});
};
InfiniteScroll.prototype.loadMore = function () {
@@ -4309,7 +4119,7 @@ S2.define('select2/dropdown/infiniteScroll',[
var $option = $(
'<li ' +
'class="select2-results__option select2-results__option--load-more"' +
'role="option" aria-disabled="true"></li>'
'role="treeitem" aria-disabled="true"></li>'
);
var message = this.options.get('translations').get('loadingMore');
@@ -4327,7 +4137,7 @@ S2.define('select2/dropdown/attachBody',[
'../utils'
], function ($, Utils) {
function AttachBody (decorated, $element, options) {
this.$dropdownParent = $(options.get('dropdownParent') || document.body);
this.$dropdownParent = options.get('dropdownParent') || $(document.body);
decorated.call(this, $element, options);
}
@@ -4335,14 +4145,27 @@ S2.define('select2/dropdown/attachBody',[
AttachBody.prototype.bind = function (decorated, container, $container) {
var self = this;
var setupResultsEvents = false;
decorated.call(this, container, $container);
container.on('open', function () {
self._showDropdown();
self._attachPositioningHandler(container);
// Must bind after the results handlers to ensure correct sizing
self._bindContainerResultHandlers(container);
if (!setupResultsEvents) {
setupResultsEvents = true;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
}
});
container.on('close', function () {
@@ -4391,44 +4214,6 @@ S2.define('select2/dropdown/attachBody',[
this.$dropdownContainer.detach();
};
AttachBody.prototype._bindContainerResultHandlers =
function (decorated, container) {
// These should only be bound once
if (this._containerResultsHandlersBound) {
return;
}
var self = this;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:message', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('select', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('unselect', function () {
self._positionDropdown();
self._resizeDropdown();
});
this._containerResultsHandlersBound = true;
};
AttachBody.prototype._attachPositioningHandler =
function (decorated, container) {
var self = this;
@@ -4439,14 +4224,14 @@ S2.define('select2/dropdown/attachBody',[
var $watchers = this.$container.parents().filter(Utils.hasScroll);
$watchers.each(function () {
Utils.StoreData(this, 'select2-scroll-position', {
$(this).data('select2-scroll-position', {
x: $(this).scrollLeft(),
y: $(this).scrollTop()
});
});
$watchers.on(scrollEvent, function (ev) {
var position = Utils.GetData(this, 'select2-scroll-position');
var position = $(this).data('select2-scroll-position');
$(this).scrollTop(position.y);
});
@@ -4505,26 +4290,16 @@ S2.define('select2/dropdown/attachBody',[
top: container.bottom
};
// Determine what the parent element is to use for calculating the offset
// Determine what the parent element is to use for calciulating the offset
var $offsetParent = this.$dropdownParent;
// For statically positioned elements, we need to get the element
// For statically positoned elements, we need to get the element
// that is determining the offset
if ($offsetParent.css('position') === 'static') {
$offsetParent = $offsetParent.offsetParent();
}
var parentOffset = {
top: 0,
left: 0
};
if (
$.contains(document.body, $offsetParent[0]) ||
$offsetParent[0].isConnected
) {
parentOffset = $offsetParent.offset();
}
var parentOffset = $offsetParent.offset();
css.top -= parentOffset.top;
css.left -= parentOffset.left;
@@ -4621,8 +4396,8 @@ S2.define('select2/dropdown/minimumResultsForSearch',[
});
S2.define('select2/dropdown/selectOnClose',[
'../utils'
], function (Utils) {
], function () {
function SelectOnClose () { }
SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -4653,7 +4428,7 @@ S2.define('select2/dropdown/selectOnClose',[
return;
}
var data = Utils.GetData($highlightedResults[0], 'data');
var data = $highlightedResults.data('data');
// Don't re-select already selected resulte
if (
@@ -4694,7 +4469,7 @@ S2.define('select2/dropdown/closeOnSelect',[
var originalEvent = evt.originalEvent;
// Don't close if the control key is being held
if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
if (originalEvent && originalEvent.ctrlKey) {
return;
}
@@ -4748,9 +4523,6 @@ S2.define('select2/i18n/en',[],function () {
},
searching: function () {
return 'Searching…';
},
removeAllItems: function () {
return 'Remove all items';
}
};
});
@@ -4989,29 +4761,66 @@ S2.define('select2/defaults',[
);
}
// If the defaults were not previously applied from an element, it is
// possible for the language option to have not been resolved
options.language = this._resolveLanguage(options.language);
if (typeof options.language === 'string') {
// Check if the language is specified with a region
if (options.language.indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = options.language.split('-');
var baseLanguage = languageParts[0];
// Always fall back to English since it will always be complete
options.language.push('en');
var uniqueLanguages = [];
for (var l = 0; l < options.language.length; l++) {
var language = options.language[l];
if (uniqueLanguages.indexOf(language) === -1) {
uniqueLanguages.push(language);
options.language = [options.language, baseLanguage];
} else {
options.language = [options.language];
}
}
options.language = uniqueLanguages;
if ($.isArray(options.language)) {
var languages = new Translation();
options.language.push('en');
options.translations = this._processTranslations(
options.language,
options.debug
);
var languageNames = options.language;
for (var l = 0; l < languageNames.length; l++) {
var name = languageNames[l];
var language = {};
try {
// Try to load it with the original name
language = Translation.loadPath(name);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
name = this.defaults.amdLanguageBase + name;
language = Translation.loadPath(name);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files.
if (options.debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + name + '" could not be ' +
'automatically loaded. A fallback will be used instead.'
);
}
continue;
}
}
languages.extend(language);
}
options.translations = languages;
} else {
var baseTranslation = Translation.loadPath(
this.defaults.amdLanguageBase + 'en'
);
var customTranslation = new Translation(options.language);
customTranslation.extend(baseTranslation);
options.translations = customTranslation;
}
return options;
};
@@ -5078,14 +4887,13 @@ S2.define('select2/defaults',[
debug: false,
dropdownAutoWidth: false,
escapeMarkup: Utils.escapeMarkup,
language: {},
language: EnglishTranslation,
matcher: matcher,
minimumInputLength: 0,
maximumInputLength: 0,
maximumSelectionLength: 0,
minimumResultsForSearch: 0,
selectOnClose: false,
scrollAfterSelect: false,
sorter: function (data) {
return data;
},
@@ -5100,103 +4908,6 @@ S2.define('select2/defaults',[
};
};
Defaults.prototype.applyFromElement = function (options, $element) {
var optionLanguage = options.language;
var defaultLanguage = this.defaults.language;
var elementLanguage = $element.prop('lang');
var parentLanguage = $element.closest('[lang]').prop('lang');
var languages = Array.prototype.concat.call(
this._resolveLanguage(elementLanguage),
this._resolveLanguage(optionLanguage),
this._resolveLanguage(defaultLanguage),
this._resolveLanguage(parentLanguage)
);
options.language = languages;
return options;
};
Defaults.prototype._resolveLanguage = function (language) {
if (!language) {
return [];
}
if ($.isEmptyObject(language)) {
return [];
}
if ($.isPlainObject(language)) {
return [language];
}
var languages;
if (!$.isArray(language)) {
languages = [language];
} else {
languages = language;
}
var resolvedLanguages = [];
for (var l = 0; l < languages.length; l++) {
resolvedLanguages.push(languages[l]);
if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = languages[l].split('-');
var baseLanguage = languageParts[0];
resolvedLanguages.push(baseLanguage);
}
}
return resolvedLanguages;
};
Defaults.prototype._processTranslations = function (languages, debug) {
var translations = new Translation();
for (var l = 0; l < languages.length; l++) {
var languageData = new Translation();
var language = languages[l];
if (typeof language === 'string') {
try {
// Try to load it with the original name
languageData = Translation.loadPath(language);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
language = this.defaults.amdLanguageBase + language;
languageData = Translation.loadPath(language);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files
if (debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + language + '" could ' +
'not be automatically loaded. A fallback will be used instead.'
);
}
}
}
} else if ($.isPlainObject(language)) {
languageData = new Translation(language);
} else {
languageData = language;
}
translations.extend(languageData);
}
return translations;
};
Defaults.prototype.set = function (key, value) {
var camelKey = $.camelCase(key);
@@ -5205,7 +4916,7 @@ S2.define('select2/defaults',[
var convertedData = Utils._convertData(data);
$.extend(true, this.defaults, convertedData);
$.extend(this.defaults, convertedData);
};
var defaults = new Defaults();
@@ -5226,10 +4937,6 @@ S2.define('select2/options',[
this.fromElement($element);
}
if ($element != null) {
this.options = Defaults.applyFromElement(this.options, $element);
}
this.options = Defaults.apply(this.options);
if ($element && $element.is('input')) {
@@ -5253,6 +4960,14 @@ S2.define('select2/options',[
this.options.disabled = $e.prop('disabled');
}
if (this.options.language == null) {
if ($e.prop('lang')) {
this.options.language = $e.prop('lang').toLowerCase();
} else if ($e.closest('[lang]').prop('lang')) {
this.options.language = $e.closest('[lang]').prop('lang');
}
}
if (this.options.dir == null) {
if ($e.prop('dir')) {
this.options.dir = $e.prop('dir');
@@ -5266,7 +4981,7 @@ S2.define('select2/options',[
$e.prop('disabled', this.options.disabled);
$e.prop('multiple', this.options.multiple);
if (Utils.GetData($e[0], 'select2Tags')) {
if ($e.data('select2Tags')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -5275,11 +4990,11 @@ S2.define('select2/options',[
);
}
Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
Utils.StoreData($e[0], 'tags', true);
$e.data('data', $e.data('select2Tags'));
$e.data('tags', true);
}
if (Utils.GetData($e[0], 'ajaxUrl')) {
if ($e.data('ajaxUrl')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'Select2: The `data-ajax-url` attribute has been changed to ' +
@@ -5288,45 +5003,21 @@ S2.define('select2/options',[
);
}
$e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
$e.attr('ajax--url', $e.data('ajaxUrl'));
$e.data('ajax--url', $e.data('ajaxUrl'));
}
var dataset = {};
function upperCaseLetter(_, letter) {
return letter.toUpperCase();
}
// Pre-load all of the attributes which are prefixed with `data-`
for (var attr = 0; attr < $e[0].attributes.length; attr++) {
var attributeName = $e[0].attributes[attr].name;
var prefix = 'data-';
if (attributeName.substr(0, prefix.length) == prefix) {
// Get the contents of the attribute after `data-`
var dataName = attributeName.substring(prefix.length);
// Get the data contents from the consistent source
// This is more than likely the jQuery data helper
var dataValue = Utils.GetData($e[0], dataName);
// camelCase the attribute name to match the spec
var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
// Store the data attribute contents into the dataset since
dataset[camelDataName] = dataValue;
}
}
// Prefer the element's `dataset` attribute if it exists
// jQuery 1.x does not correctly handle data attributes with multiple dashes
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
dataset = $.extend(true, {}, $e[0].dataset, dataset);
dataset = $.extend(true, {}, $e[0].dataset, $e.data());
} else {
dataset = $e.data();
}
// Prefer our internal data cache if it exists
var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
var data = $.extend(true, {}, dataset);
data = Utils._convertData(data);
@@ -5363,8 +5054,8 @@ S2.define('select2/core',[
'./keys'
], function ($, Options, Utils, KEYS) {
var Select2 = function ($element, options) {
if (Utils.GetData($element[0], 'select2') != null) {
Utils.GetData($element[0], 'select2').destroy();
if ($element.data('select2') != null) {
$element.data('select2').destroy();
}
this.$element = $element;
@@ -5380,7 +5071,7 @@ S2.define('select2/core',[
// Set up the tabindex
var tabindex = $element.attr('tabindex') || 0;
Utils.StoreData($element[0], 'old-tabindex', tabindex);
$element.data('old-tabindex', tabindex);
$element.attr('tabindex', '-1');
// Set up containers and adapters
@@ -5441,9 +5132,6 @@ S2.define('select2/core',[
// Synchronize any monitored attributes
this._syncAttributes();
Utils.StoreData($element[0], 'select2', this);
// Ensure backwards compatibility with $element.data('select2').
$element.data('select2', this);
};
@@ -5520,12 +5208,6 @@ S2.define('select2/core',[
return null;
}
if (method == 'computedstyle') {
var computedStyle = window.getComputedStyle($element[0]);
return computedStyle.width;
}
return method;
};
@@ -5566,8 +5248,8 @@ S2.define('select2/core',[
if (observer != null) {
this._observer = new observer(function (mutations) {
self._syncA();
self._syncS(null, mutations);
$.each(mutations, self._syncA);
$.each(mutations, self._syncS);
});
this._observer.observe(this.$element[0], {
attributes: true,
@@ -5689,7 +5371,7 @@ S2.define('select2/core',[
if (self.isOpen()) {
if (key === KEYS.ESC || key === KEYS.TAB ||
(key === KEYS.UP && evt.altKey)) {
self.close(evt);
self.close();
evt.preventDefault();
} else if (key === KEYS.ENTER) {
@@ -5723,7 +5405,7 @@ S2.define('select2/core',[
Select2.prototype._syncAttributes = function () {
this.options.set('disabled', this.$element.prop('disabled'));
if (this.isDisabled()) {
if (this.options.get('disabled')) {
if (this.isOpen()) {
this.close();
}
@@ -5734,7 +5416,7 @@ S2.define('select2/core',[
}
};
Select2.prototype._isChangeMutation = function (evt, mutations) {
Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = false;
var self = this;
@@ -5762,22 +5444,7 @@ S2.define('select2/core',[
}
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
changed = true;
} else if ($.isArray(mutations)) {
$.each(mutations, function(evt, mutation) {
if (self._isChangeMutation(evt, mutation)) {
// We've found a change mutation.
// Let's escape from the loop and continue
changed = true;
return false;
}
});
}
return changed;
};
Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = this._isChangeMutation(evt, mutations);
var self = this;
// Only re-pull the data if we think there is a change
if (changed) {
@@ -5799,8 +5466,7 @@ S2.define('select2/core',[
'open': 'opening',
'close': 'closing',
'select': 'selecting',
'unselect': 'unselecting',
'clear': 'clearing'
'unselect': 'unselecting'
};
if (args === undefined) {
@@ -5828,7 +5494,7 @@ S2.define('select2/core',[
};
Select2.prototype.toggleDropdown = function () {
if (this.isDisabled()) {
if (this.options.get('disabled')) {
return;
}
@@ -5844,40 +5510,15 @@ S2.define('select2/core',[
return;
}
if (this.isDisabled()) {
return;
}
this.trigger('query', {});
};
Select2.prototype.close = function (evt) {
Select2.prototype.close = function () {
if (!this.isOpen()) {
return;
}
this.trigger('close', { originalEvent : evt });
};
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
Select2.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
Select2.prototype.isDisabled = function () {
return this.options.get('disabled');
this.trigger('close', {});
};
Select2.prototype.isOpen = function () {
@@ -5954,7 +5595,7 @@ S2.define('select2/core',[
});
}
this.$element.val(newVal).trigger('input').trigger('change');
this.$element.val(newVal).trigger('change');
};
Select2.prototype.destroy = function () {
@@ -5980,12 +5621,10 @@ S2.define('select2/core',[
this._syncS = null;
this.$element.off('.select2');
this.$element.attr('tabindex',
Utils.GetData(this.$element[0], 'old-tabindex'));
this.$element.attr('tabindex', this.$element.data('old-tabindex'));
this.$element.removeClass('select2-hidden-accessible');
this.$element.attr('aria-hidden', 'false');
Utils.RemoveData(this.$element[0]);
this.$element.removeData('select2');
this.dataAdapter.destroy();
@@ -6013,7 +5652,7 @@ S2.define('select2/core',[
this.$container.addClass('select2-container--' + this.options.get('theme'));
Utils.StoreData($container[0], 'element', this.$element);
$container.data('element', this.$element);
return $container;
};
@@ -6033,9 +5672,8 @@ S2.define('jquery.select2',[
'jquery-mousewheel',
'./select2/core',
'./select2/defaults',
'./select2/utils'
], function ($, _, Select2, Defaults, Utils) {
'./select2/defaults'
], function ($, _, Select2, Defaults) {
if ($.fn.select2 == null) {
// All methods that should return the element
var thisMethods = ['open', 'close', 'destroy'];
@@ -6056,7 +5694,7 @@ S2.define('jquery.select2',[
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = Utils.GetData(this, 'select2');
var instance = $(this).data('select2');
if (instance == null && window.console && console.error) {
console.error(
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -2
View File
File diff suppressed because one or more lines are too long
+9
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
+155
View File
@@ -0,0 +1,155 @@
(function($) {
$.extend($.summernote.lang, {
'ko-KR': {
font: {
bold: '굵게',
italic: '기울임꼴',
underline: '밑줄',
clear: '글자 효과 없애기',
height: '줄간격',
name: '글꼴',
superscript: '위 첨자',
subscript: '아래 첨자',
strikethrough: '취소선',
size: '글자 크기'
},
image: {
image: '사진',
insert: '사진 추가',
resizeFull: '100% 크기로 변경',
resizeHalf: '50% 크기로 변경',
resizeQuarter: '25% 크기로 변경',
floatLeft: '왼쪽 정렬',
floatRight: '오른쪽 정렬',
floatNone: '정렬하지 않음',
shapeRounded: '스타일: 둥근 모서리',
shapeCircle: '스타일: 원형',
shapeThumbnail: '스타일: 액자',
shapeNone: '스타일: 없음',
dragImageHere: '텍스트 혹은 사진을 이곳으로 끌어오세요',
dropImage: '텍스트 혹은 사진을 내려놓으세요',
selectFromFiles: '파일 선택',
maximumFileSize: 'Maximum file size',
maximumFileSizeError: 'Maximum file size exceeded.',
url: '사진 URL',
remove: '사진 삭제',
original: 'Original'
},
video: {
video: '동영상',
videoLink: '동영상 링크',
insert: '동영상 추가',
url: '동영상 URL',
providers: '(YouTube, Vimeo, Vine, Instagram, DailyMotion, Youku 사용 가능)'
},
link: {
link: '링크',
insert: '링크 추가',
unlink: '링크 삭제',
edit: '수정',
textToDisplay: '링크에 표시할 내용',
url: '이동할 URL',
openInNewWindow: '새창으로 열기'
},
table: {
table: '테이블',
addRowAbove: 'Add row above',
addRowBelow: 'Add row below',
addColLeft: 'Add column left',
addColRight: 'Add column right',
delRow: 'Delete row',
delCol: 'Delete column',
delTable: 'Delete table'
},
hr: {
insert: '구분선 추가'
},
style: {
style: '스타일',
p: '본문',
blockquote: '인용구',
pre: '코드',
h1: '제목 1',
h2: '제목 2',
h3: '제목 3',
h4: '제목 4',
h5: '제목 5',
h6: '제목 6'
},
lists: {
unordered: '글머리 기호',
ordered: '번호 매기기'
},
options: {
help: '도움말',
fullscreen: '전체 화면',
codeview: '코드 보기'
},
paragraph: {
paragraph: '문단 정렬',
outdent: '내어쓰기',
indent: '들여쓰기',
left: '왼쪽 정렬',
center: '가운데 정렬',
right: '오른쪽 정렬',
justify: '양쪽 정렬'
},
color: {
recent: '마지막으로 사용한 색',
more: '다른 색 선택',
background: '배경색',
foreground: '글자색',
transparent: '투명',
setTransparent: '투명',
reset: '취소',
resetToDefault: '기본 값으로 변경'
},
shortcut: {
shortcuts: '키보드 단축키',
close: '닫기',
textFormatting: '글자 스타일 적용',
action: '기능',
paragraphFormatting: '문단 스타일 적용',
documentStyle: '문서 스타일 적용',
extraKeys: 'Extra keys'
},
help: {
'insertParagraph': 'Insert Paragraph',
'undo': 'Undoes the last command',
'redo': 'Redoes the last command',
'tab': 'Tab',
'untab': 'Untab',
'bold': 'Set a bold style',
'italic': 'Set a italic style',
'underline': 'Set a underline style',
'strikethrough': 'Set a strikethrough style',
'removeFormat': 'Clean a style',
'justifyLeft': 'Set left align',
'justifyCenter': 'Set center align',
'justifyRight': 'Set right align',
'justifyFull': 'Set full align',
'insertUnorderedList': 'Toggle unordered list',
'insertOrderedList': 'Toggle ordered list',
'outdent': 'Outdent on current paragraph',
'indent': 'Indent on current paragraph',
'formatPara': 'Change current block\'s format as a paragraph(P tag)',
'formatH1': 'Change current block\'s format as H1',
'formatH2': 'Change current block\'s format as H2',
'formatH3': 'Change current block\'s format as H3',
'formatH4': 'Change current block\'s format as H4',
'formatH5': 'Change current block\'s format as H5',
'formatH6': 'Change current block\'s format as H6',
'insertHorizontalRule': 'Insert horizontal rule',
'linkDialog.show': 'Show Link Dialog'
},
history: {
undo: '실행 취소',
redo: '다시 실행'
},
specialChar: {
specialChar: '특수문자',
select: '특수문자를 선택하세요'
}
}
});
})(jQuery);
@@ -0,0 +1,16 @@
.ext-databasic {
position: relative;
display: block;
min-height: 50px;
background-color: cyan;
text-align: center;
padding: 20px;
border: 1px solid white;
border-radius: 10px;
}
.ext-databasic p {
color: white;
font-size: 1.2em;
margin: 0;
}
@@ -0,0 +1,292 @@
(function(factory) {
/* global define */
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(window.jQuery);
}
}(function($) {
// pull in some summernote core functions
var ui = $.summernote.ui;
var dom = $.summernote.dom;
// define the popover plugin
var DataBasicPlugin = function(context) {
var self = this;
var options = context.options;
var lang = options.langInfo;
self.icon = '<i class="fa fa-object-group"/>';
// add context menu button for dialog
context.memo('button.databasic', function() {
return ui.button({
contents: self.icon,
tooltip: lang.databasic.insert,
click: context.createInvokeHandler('databasic.showDialog')
}).render();
});
// add popover edit button
context.memo('button.databasicDialog', function() {
return ui.button({
contents: self.icon,
tooltip: lang.databasic.edit,
click: context.createInvokeHandler('databasic.showDialog')
}).render();
});
// add popover size buttons
context.memo('button.databasicSize100', function() {
return ui.button({
contents: '<span class="note-fontsize-10">100%</span>',
tooltip: lang.image.resizeFull,
click: context.createInvokeHandler('editor.resize', '1')
}).render();
});
context.memo('button.databasicSize50', function() {
return ui.button({
contents: '<span class="note-fontsize-10">50%</span>',
tooltip: lang.image.resizeHalf,
click: context.createInvokeHandler('editor.resize', '0.5')
}).render();
});
context.memo('button.databasicSize25', function() {
return ui.button({
contents: '<span class="note-fontsize-10">25%</span>',
tooltip: lang.image.resizeQuarter,
click: context.createInvokeHandler('editor.resize', '0.25')
}).render();
});
self.events = {
'summernote.init': function(we, e) {
// update existing containers
$('data.ext-databasic', e.editable).each(function() { self.setContent($(this)); });
// TODO: make this an undo snapshot...
},
'summernote.keyup summernote.mouseup summernote.change summernote.scroll': function() {
self.update();
},
'summernote.dialog.shown': function() {
self.hidePopover();
}
};
self.initialize = function() {
// create dialog markup
var $container = options.dialogsInBody ? $(document.body) : context.layoutInfo.editor;
var body = '<div class="form-group row-fluid">' +
'<label>' + lang.databasic.testLabel + '</label>' +
'<input class="ext-databasic-test form-control" type="text" />' +
'</div>';
var footer = '<button href="#" class="btn btn-primary ext-databasic-save">' + lang.databasic.insert + '</button>';
self.$dialog = ui.dialog({
title: lang.databasic.name,
fade: options.dialogsFade,
body: body,
footer: footer
}).render().appendTo($container);
// create popover
self.$popover = ui.popover({
className: 'ext-databasic-popover'
}).render().appendTo('body');
var $content = self.$popover.find('.popover-content');
context.invoke('buttons.build', $content, options.popover.databasic);
};
self.destroy = function() {
self.$popover.remove();
self.$popover = null;
self.$dialog.remove();
self.$dialog = null;
};
self.update = function() {
// Prevent focusing on editable when invoke('code') is executed
if (!context.invoke('editor.hasFocus')) {
self.hidePopover();
return;
}
var rng = context.invoke('editor.createRange');
var visible = false;
if (rng.isOnData()) {
var $data = $(rng.sc).closest('data.ext-databasic');
if ($data.length) {
var pos = dom.posFromPlaceholder($data[0]);
self.$popover.css({
display: 'block',
left: pos.left,
top: pos.top
});
// save editor target to let size buttons resize the container
context.invoke('editor.saveTarget', $data[0]);
visible = true;
}
}
// hide if not visible
if (!visible) {
self.hidePopover();
}
};
self.hidePopover = function() {
self.$popover.hide();
};
// define plugin dialog
self.getInfo = function() {
var rng = context.invoke('editor.createRange');
if (rng.isOnData()) {
var $data = $(rng.sc).closest('data.ext-databasic');
if ($data.length) {
// Get the first node on range(for edit).
return {
node: $data,
test: $data.attr('data-test')
};
}
}
return {};
};
self.setContent = function($node) {
$node.html('<p contenteditable="false">' + self.icon + ' ' + lang.databasic.name + ': ' +
$node.attr('data-test') + '</p>');
};
self.updateNode = function(info) {
self.setContent(info.node
.attr('data-test', info.test));
};
self.createNode = function(info) {
var $node = $('<data class="ext-databasic"></data>');
if ($node) {
// save node to info structure
info.node = $node;
// insert node into editor dom
context.invoke('editor.insertNode', $node[0]);
}
return $node;
};
self.showDialog = function() {
var info = self.getInfo();
var newNode = !info.node;
context.invoke('editor.saveRange');
self
.openDialog(info)
.then(function(dialogInfo) {
// [workaround] hide dialog before restore range for IE range focus
ui.hideDialog(self.$dialog);
context.invoke('editor.restoreRange');
// insert a new node
if (newNode) {
self.createNode(info);
}
// update info with dialog info
$.extend(info, dialogInfo);
self.updateNode(info);
})
.fail(function() {
context.invoke('editor.restoreRange');
});
};
self.openDialog = function(info) {
return $.Deferred(function(deferred) {
var $inpTest = self.$dialog.find('.ext-databasic-test');
var $saveBtn = self.$dialog.find('.ext-databasic-save');
var onKeyup = function(event) {
if (event.keyCode === 13) {
$saveBtn.trigger('click');
}
};
ui.onDialogShown(self.$dialog, function() {
context.triggerEvent('dialog.shown');
$inpTest.val(info.test).on('input', function() {
ui.toggleBtn($saveBtn, $inpTest.val());
}).trigger('focus').on('keyup', onKeyup);
$saveBtn
.text(info.node ? lang.databasic.edit : lang.databasic.insert)
.click(function(event) {
event.preventDefault();
deferred.resolve({ test: $inpTest.val() });
});
// init save button
ui.toggleBtn($saveBtn, $inpTest.val());
});
ui.onDialogHidden(self.$dialog, function() {
$inpTest.off('input keyup');
$saveBtn.off('click');
if (deferred.state() === 'pending') {
deferred.reject();
}
});
ui.showDialog(self.$dialog);
});
};
};
// Extends summernote
$.extend(true, $.summernote, {
plugins: {
databasic: DataBasicPlugin
},
options: {
popover: {
databasic: [
['databasic', ['databasicDialog', 'databasicSize100', 'databasicSize50', 'databasicSize25']]
]
}
},
// add localization texts
lang: {
'en-US': {
databasic: {
name: 'Basic Data Container',
insert: 'insert basic data container',
edit: 'edit basic data container',
testLabel: 'test input'
}
}
}
});
}));
@@ -0,0 +1,81 @@
(function(factory) {
/* global define */
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(window.jQuery);
}
}(function($) {
// Extends plugins for adding hello.
// - plugin is external module for customizing.
$.extend($.summernote.plugins, {
/**
* @param {Object} context - context object has status of editor.
*/
'hello': function(context) {
var self = this;
// ui has renders to build ui elements.
// - you can create a button with `ui.button`
var ui = $.summernote.ui;
// add hello button
context.memo('button.hello', function() {
// create button
var button = ui.button({
contents: '<i class="fa fa-child"/> Hello',
tooltip: 'hello',
click: function() {
self.$panel.show();
self.$panel.hide(500);
// invoke insertText method with 'hello' on editor module.
context.invoke('editor.insertText', 'hello');
}
});
// create jQuery object from button instance.
var $hello = button.render();
return $hello;
});
// This events will be attached when editor is initialized.
this.events = {
// This will be called after modules are initialized.
'summernote.init': function(we, e) {
console.log('summernote initialized', we, e);
},
// This will be called when user releases a key on editable.
'summernote.keyup': function(we, e) {
console.log('summernote keyup', we, e);
}
};
// This method will be called when editor is initialized by $('..').summernote();
// You can create elements for plugin
this.initialize = function() {
this.$panel = $('<div class="hello-panel"/>').css({
position: 'absolute',
width: 100,
height: 100,
left: '50%',
top: '50%',
background: 'red'
}).hide();
this.$panel.appendTo('body');
};
// This methods will be called when editor is destroyed by $('..').summernote('destroy');
// You should remove elements on `initialize`.
this.destroy = function() {
this.$panel.remove();
this.$panel = null;
};
}
});
}));
@@ -0,0 +1,153 @@
/* Forked from https://github.com/asiffermann/summernote-image-title */
(function (factory) {
/* Global define */
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(window.jQuery);
}
}(function ($) {
$.extend(true, $.summernote.lang, {
'en-US': {
imageFlip: {
edit: 'Flip image',
flipLabel: 'Alternative Image'
}
},
'ko-KR': {
imageFlip: {
edit: '이미지 전환',
flipLabel: '대체 이미지( , 로 구분)'
}
},
});
$.extend($.summernote.options, {
imageFlip: {
icon: '<i class="note-icon-pencil"/>',
tooltip: 'Image Flip'
}
});
$.extend($.summernote.plugins, {
'imageFlip': function (context) {
var self = this;
var ui = $.summernote.ui;
var $note = context.layoutInfo.note;
var $editor = context.layoutInfo.editor;
var $editable = context.layoutInfo.editable;
var $toolbar = context.layoutInfo.toolbar;
if (typeof context.options.imageFlip === 'undefined') {
context.options.imageFlip = {};
}
var options = context.options;
var lang = options.langInfo;
context.memo('button.imageFlip', function () {
var button = ui.button({
contents: ui.icon(options.icons.pencil),
container: false,
tooltip: lang.imageFlip.edit,
click: function (e) {
context.invoke('imageFlip.show');
}
});
return button.render();
});
this.initialize = function () {
var $container = options.dialogsInBody ? $(document.body) : $editor;
var body = '<div class="form-group">' +
'<label>' + lang.imageFlip.flipLabel + '</label>' +
'<input class="note-image-flip-text form-control" type="text" />' +
'</div>';
var footer = '<button href="#" class="btn btn-primary note-image-flip-btn">' + lang.imageFlip.edit + '</button>';
this.$dialog = ui.dialog({
title: lang.imageFlip.edit,
body: body,
footer: footer
}).render().appendTo($container);
};
this.destroy = function () {
ui.hideDialog(this.$dialog);
this.$dialog.remove();
};
this.bindEnterKey = function ($input, $btn) {
$input.on('keypress', function (event) {
if (event.keyCode === 13) {
$btn.trigger('click');
}
});
};
this.show = function () {
var $img = $($editable.data('target'));
var imgInfo = {
imgDom: $img,
flip: $img.data('flip'),
};
this.showLinkDialog(imgInfo).then(function (imgInfo) {
ui.hideDialog(self.$dialog);
var $img = imgInfo.imgDom;
if (imgInfo.flip) {
$img.attr('data-flip', imgInfo.flip);
}
else {
$img.removeData('flip');
}
$note.val(context.invoke('code'));
$note.change();
});
};
this.showLinkDialog = function (imgInfo) {
return $.Deferred(function (deferred) {
var $imageFlip = self.$dialog.find('.note-image-flip-text');
var $editBtn = self.$dialog.find('.note-image-flip-btn');
ui.onDialogShown(self.$dialog, function () {
context.triggerEvent('dialog.shown');
$editBtn.click(function (event) {
event.preventDefault();
deferred.resolve({
imgDom: imgInfo.imgDom,
flip: $imageFlip.val(),
});
});
$imageFlip.val(imgInfo.flip).trigger('focus');
self.bindEnterKey($imageFlip, $editBtn);
});
ui.onDialogHidden(self.$dialog, function () {
$editBtn.off('click');
if (deferred.state() === 'pending') {
deferred.reject();
}
});
ui.showDialog(self.$dialog);
});
};
}
});
}));
@@ -0,0 +1,312 @@
(function(factory) {
/* global define */
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(window.jQuery);
}
}(function($) {
$.extend($.summernote.plugins, {
'specialchars': function(context) {
var self = this;
var ui = $.summernote.ui;
var $editor = context.layoutInfo.editor;
var options = context.options;
var lang = options.langInfo;
var KEY = {
UP: 38,
DOWN: 40,
LEFT: 37,
RIGHT: 39,
ENTER: 13
};
var COLUMN_LENGTH = 15;
var COLUMN_WIDTH = 35;
var currentColumn = 0;
var currentRow = 0;
var totalColumn = 0;
var totalRow = 0;
// special characters data set
var specialCharDataSet = [
'&quot;', '&amp;', '&lt;', '&gt;', '&iexcl;', '&cent;',
'&pound;', '&curren;', '&yen;', '&brvbar;', '&sect;',
'&uml;', '&copy;', '&ordf;', '&laquo;', '&not;',
'&reg;', '&macr;', '&deg;', '&plusmn;', '&sup2;',
'&sup3;', '&acute;', '&micro;', '&para;', '&middot;',
'&cedil;', '&sup1;', '&ordm;', '&raquo;', '&frac14;',
'&frac12;', '&frac34;', '&iquest;', '&times;', '&divide;',
'&fnof;', '&circ;', '&tilde;', '&ndash;', '&mdash;',
'&lsquo;', '&rsquo;', '&sbquo;', '&ldquo;', '&rdquo;',
'&bdquo;', '&dagger;', '&Dagger;', '&bull;', '&hellip;',
'&permil;', '&prime;', '&Prime;', '&lsaquo;', '&rsaquo;',
'&oline;', '&frasl;', '&euro;', '&image;', '&weierp;',
'&real;', '&trade;', '&alefsym;', '&larr;', '&uarr;',
'&rarr;', '&darr;', '&harr;', '&crarr;', '&lArr;',
'&uArr;', '&rArr;', '&dArr;', '&hArr;', '&forall;',
'&part;', '&exist;', '&empty;', '&nabla;', '&isin;',
'&notin;', '&ni;', '&prod;', '&sum;', '&minus;',
'&lowast;', '&radic;', '&prop;', '&infin;', '&ang;',
'&and;', '&or;', '&cap;', '&cup;', '&int;',
'&there4;', '&sim;', '&cong;', '&asymp;', '&ne;',
'&equiv;', '&le;', '&ge;', '&sub;', '&sup;',
'&nsub;', '&sube;', '&supe;', '&oplus;', '&otimes;',
'&perp;', '&sdot;', '&lceil;', '&rceil;', '&lfloor;',
'&rfloor;', '&loz;', '&spades;', '&clubs;', '&hearts;',
'&diams;'
];
context.memo('button.specialchars', function() {
return ui.button({
contents: '<i class="fa fa-font fa-flip-vertical">',
tooltip: lang.specialChar.specialChar,
click: function() {
self.show();
}
}).render();
});
/**
* Make Special Characters Table
*
* @member plugin.specialChar
* @private
* @return {jQuery}
*/
this.makeSpecialCharSetTable = function() {
var $table = $('<table/>');
$.each(specialCharDataSet, function(idx, text) {
var $td = $('<td/>').addClass('note-specialchar-node');
var $tr = (idx % COLUMN_LENGTH === 0) ? $('<tr/>') : $table.find('tr').last();
var $button = ui.button({
callback: function($node) {
$node.html(text);
$node.attr('title', text);
$node.attr('data-value', encodeURIComponent(text));
$node.css({
width: COLUMN_WIDTH,
'margin-right': '2px',
'margin-bottom': '2px'
});
}
}).render();
$td.append($button);
$tr.append($td);
if (idx % COLUMN_LENGTH === 0) {
$table.append($tr);
}
});
totalRow = $table.find('tr').length;
totalColumn = COLUMN_LENGTH;
return $table;
};
this.initialize = function() {
var $container = options.dialogsInBody ? $(document.body) : $editor;
var body = '<div class="form-group row-fluid">' + this.makeSpecialCharSetTable()[0].outerHTML + '</div>';
this.$dialog = ui.dialog({
title: lang.specialChar.select,
body: body
}).render().appendTo($container);
};
this.show = function() {
var text = context.invoke('editor.getSelectedText');
context.invoke('editor.saveRange');
this.showSpecialCharDialog(text).then(function(selectChar) {
context.invoke('editor.restoreRange');
// build node
var $node = $('<span></span>').html(selectChar)[0];
if ($node) {
// insert video node
context.invoke('editor.insertNode', $node);
}
}).fail(function() {
context.invoke('editor.restoreRange');
});
};
/**
* show image dialog
*
* @param {jQuery} $dialog
* @return {Promise}
*/
this.showSpecialCharDialog = function(text) {
return $.Deferred(function(deferred) {
var $specialCharDialog = self.$dialog;
var $specialCharNode = $specialCharDialog.find('.note-specialchar-node');
var $selectedNode = null;
var ARROW_KEYS = [KEY.UP, KEY.DOWN, KEY.LEFT, KEY.RIGHT];
var ENTER_KEY = KEY.ENTER;
function addActiveClass($target) {
if (!$target) {
return;
}
$target.find('button').addClass('active');
$selectedNode = $target;
}
function removeActiveClass($target) {
$target.find('button').removeClass('active');
$selectedNode = null;
}
// find next node
function findNextNode(row, column) {
var findNode = null;
$.each($specialCharNode, function(idx, $node) {
var findRow = Math.ceil((idx + 1) / COLUMN_LENGTH);
var findColumn = ((idx + 1) % COLUMN_LENGTH === 0) ? COLUMN_LENGTH : (idx + 1) % COLUMN_LENGTH;
if (findRow === row && findColumn === column) {
findNode = $node;
return false;
}
});
return $(findNode);
}
function arrowKeyHandler(keyCode) {
// left, right, up, down key
var $nextNode;
var lastRowColumnLength = $specialCharNode.length % totalColumn;
if (KEY.LEFT === keyCode) {
if (currentColumn > 1) {
currentColumn = currentColumn - 1;
} else if (currentRow === 1 && currentColumn === 1) {
currentColumn = lastRowColumnLength;
currentRow = totalRow;
} else {
currentColumn = totalColumn;
currentRow = currentRow - 1;
}
} else if (KEY.RIGHT === keyCode) {
if (currentRow === totalRow && lastRowColumnLength === currentColumn) {
currentColumn = 1;
currentRow = 1;
} else if (currentColumn < totalColumn) {
currentColumn = currentColumn + 1;
} else {
currentColumn = 1;
currentRow = currentRow + 1;
}
} else if (KEY.UP === keyCode) {
if (currentRow === 1 && lastRowColumnLength < currentColumn) {
currentRow = totalRow - 1;
} else {
currentRow = currentRow - 1;
}
} else if (KEY.DOWN === keyCode) {
currentRow = currentRow + 1;
}
if (currentRow === totalRow && currentColumn > lastRowColumnLength) {
currentRow = 1;
} else if (currentRow > totalRow) {
currentRow = 1;
} else if (currentRow < 1) {
currentRow = totalRow;
}
$nextNode = findNextNode(currentRow, currentColumn);
if ($nextNode) {
removeActiveClass($selectedNode);
addActiveClass($nextNode);
}
}
function enterKeyHandler() {
if (!$selectedNode) {
return;
}
deferred.resolve(decodeURIComponent($selectedNode.find('button').attr('data-value')));
$specialCharDialog.modal('hide');
}
function keyDownEventHandler(event) {
event.preventDefault();
var keyCode = event.keyCode;
if (keyCode === undefined || keyCode === null) {
return;
}
// check arrowKeys match
if (ARROW_KEYS.indexOf(keyCode) > -1) {
if ($selectedNode === null) {
addActiveClass($specialCharNode.eq(0));
currentColumn = 1;
currentRow = 1;
return;
}
arrowKeyHandler(keyCode);
} else if (keyCode === ENTER_KEY) {
enterKeyHandler();
}
return false;
}
// remove class
removeActiveClass($specialCharNode);
// find selected node
if (text) {
for (var i = 0; i < $specialCharNode.length; i++) {
var $checkNode = $($specialCharNode[i]);
if ($checkNode.text() === text) {
addActiveClass($checkNode);
currentRow = Math.ceil((i + 1) / COLUMN_LENGTH);
currentColumn = (i + 1) % COLUMN_LENGTH;
}
}
}
ui.onDialogShown(self.$dialog, function() {
$(document).on('keydown', keyDownEventHandler);
self.$dialog.find('button').tooltip();
$specialCharNode.on('click', function(event) {
event.preventDefault();
deferred.resolve(decodeURIComponent($(event.currentTarget).find('button').attr('data-value')));
ui.hideDialog(self.$dialog);
});
});
ui.onDialogHidden(self.$dialog, function() {
$specialCharNode.off('click');
self.$dialog.find('button').tooltip('destroy');
$(document).off('keydown', keyDownEventHandler);
if (deferred.state() === 'pending') {
deferred.reject();
}
});
ui.showDialog(self.$dialog);
});
};
}
});
}));
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+71 -122
View File
@@ -1,56 +1,54 @@
<?php
namespace sammo;
define('ROOT', realpath(__DIR__ . '/..'));
define('ROOT', realpath(__dir__.'/..'));
setlocale(LC_ALL, 'ko_KR.UTF-8');
date_default_timezone_set('Asia/Seoul');
mb_internal_encoding("UTF-8");
mb_http_output('UTF-8');
mb_regex_encoding('UTF-8');
mb_regex_encoding('UTF-8');
ini_set("session.cache_expire", '10080'); // minutes
ini_set("session.gc_maxlifetime", '604800'); // seconds
ini_set("session.cache_expire", 10080); // minutes
ini_set("session.gc_maxlifetime", 604800); // seconds
function getFriendlyErrorType($type)
{
switch ($type) {
case E_ERROR: // 1 //
return 'E_ERROR';
case E_WARNING: // 2 //
return 'E_WARNING';
case E_PARSE: // 4 //
return 'E_PARSE';
case E_NOTICE: // 8 //
return 'E_NOTICE';
case E_CORE_ERROR: // 16 //
return 'E_CORE_ERROR';
case E_CORE_WARNING: // 32 //
return 'E_CORE_WARNING';
case E_COMPILE_ERROR: // 64 //
return 'E_COMPILE_ERROR';
case E_COMPILE_WARNING: // 128 //
return 'E_COMPILE_WARNING';
case E_USER_ERROR: // 256 //
return 'E_USER_ERROR';
case E_USER_WARNING: // 512 //
return 'E_USER_WARNING';
case E_USER_NOTICE: // 1024 //
return 'E_USER_NOTICE';
case E_STRICT: // 2048 //
return 'E_STRICT';
case E_RECOVERABLE_ERROR: // 4096 //
return 'E_RECOVERABLE_ERROR';
case E_DEPRECATED: // 8192 //
return 'E_DEPRECATED';
case E_USER_DEPRECATED: // 16384 //
return 'E_USER_DEPRECATED';
}
return "{$type}";
function getFriendlyErrorType($type)
{
switch($type)
{
case E_ERROR: // 1 //
return 'E_ERROR';
case E_WARNING: // 2 //
return 'E_WARNING';
case E_PARSE: // 4 //
return 'E_PARSE';
case E_NOTICE: // 8 //
return 'E_NOTICE';
case E_CORE_ERROR: // 16 //
return 'E_CORE_ERROR';
case E_CORE_WARNING: // 32 //
return 'E_CORE_WARNING';
case E_COMPILE_ERROR: // 64 //
return 'E_COMPILE_ERROR';
case E_COMPILE_WARNING: // 128 //
return 'E_COMPILE_WARNING';
case E_USER_ERROR: // 256 //
return 'E_USER_ERROR';
case E_USER_WARNING: // 512 //
return 'E_USER_WARNING';
case E_USER_NOTICE: // 1024 //
return 'E_USER_NOTICE';
case E_STRICT: // 2048 //
return 'E_STRICT';
case E_RECOVERABLE_ERROR: // 4096 //
return 'E_RECOVERABLE_ERROR';
case E_DEPRECATED: // 8192 //
return 'E_DEPRECATED';
case E_USER_DEPRECATED: // 16384 //
return 'E_USER_DEPRECATED';
}
return "{$type}";
}
function getExceptionTraceAsString(\Throwable $exception)
{
function getExceptionTraceAsString($exception) {
//https://gist.github.com/abtris/1437966
$rtn = "";
$count = 0;
@@ -74,124 +72,75 @@ function getExceptionTraceAsString(\Throwable $exception)
$args[] = get_resource_type($arg);
} else {
$args[] = $arg;
}
}
}
}
$args = join(", ", $args);
}
$rtn[] = sprintf(
"#%s %s:%s %s(%s)",
$count,
isset($frame['file']) ? $frame['file'] : 'unknown file',
isset($frame['line']) ? $frame['line'] : 'unknown line',
(isset($frame['class'])) ? $frame['class'] . $frame['type'] . $frame['function'] : $frame['function'],
$args
);
$rtn[] = sprintf( "#%s %s:%s %s(%s)",
$count,
isset($frame['file']) ? $frame['file'] : 'unknown file',
isset($frame['line']) ? $frame['line'] : 'unknown line',
(isset($frame['class'])) ? $frame['class'].$frame['type'].$frame['function'] : $frame['function'],
$args );
$count++;
}
return $rtn;
}
function logError(string $err, string $errstr, string $errpath, array $trace)
{
$fdb = FileDB::db(ROOT . '/d_log/err_log.sqlite3', ROOT . '/f_install/sql/err_log.sql');
function logError(string $err, string $errstr, string $errpath, array $trace){
$fdb = FileDB::db(ROOT.'/d_log/err_log.sqlite3', ROOT.'/f_install/sql/err_log.sql');
$date = date("Ymd_His");
$err = str_replace(ROOT, '{ROOT}', $err);
$errstr = str_replace(ROOT, '{ROOT}', $errstr);
$errpath = str_replace(ROOT, '{ROOT}', $errpath);
$trace = array_map(function (string $text) {
$trace = array_map(function(string $text){
return str_replace(ROOT, '{ROOT}', $text);
}, $trace);
$owner = Util::get_client_ip();
$session = Session::getInstance();
if ($session->isLoggedIn(true)) {
$owner .= '(' . $session->getUserID() . ',' . $session->userName . ')';
if($session->isLoggedIn(true)){
$owner .= '('.$session->getUserID().','.$session->userName.')';
}
$fdb->insert('err_log', [
'date' => $date,
'err' => $err,
'errstr' => $errstr,
'errpath' => $errpath,
'trace' => Json::encode($trace),
'webuser' => $owner
'date'=>$date,
'err'=>$err,
'errstr'=>$errstr,
'errpath'=>$errpath,
'trace'=>Json::encode($trace),
'webuser'=>$owner
]);
}
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline)
{
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext){
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall
// through to the standard PHP error handler
return false;
}
$e = new \Exception();
logError(
getFriendlyErrorType($errno),
$errstr,
$errfile . ':' . $errline,
$errfile.':'.$errline,
getExceptionTraceAsString($e)
);
return true;
}
set_error_handler("\\sammo\\logErrorByCustomHandler");
set_error_handler("\sammo\logErrorByCustomHandler");
function logExceptionByCustomHandler(\Throwable $e, bool $withDie = true)
{
function logExceptionByCustomHandler(\Throwable $e){
logError(
get_class($e),
$e->getMessage(),
$e->getFile() . ':' . $e->getLine(),
$e->getFile().':'.$e->getLine(),
getExceptionTraceAsString($e)
);
if($withDie){
echo $e->getTraceAsString();
throw $e;
}
}
set_exception_handler('\\sammo\\logExceptionByCustomHandler');
function checkForFatal()
{
$error = error_get_last();
if($error === null){
return;
}
if (($error["type"]??0) == E_ERROR) {
logErrorByCustomHandler($error["type"], $error["message"], $error["file"], $error["line"]);
}
}
register_shutdown_function("\\sammo\\checkForFatal");
function getAPIExecutorClass($path)
{
static $basePath = __NAMESPACE__ . '\\API\\';
if (is_string($path)) {
} else if (is_array($path)) {
$path = join('\\', $path);
} else {
throw new \InvalidArgumentException("{$path}는 올바른 API 지시자가 아님");
}
$classPath = str_replace('/', '\\', $basePath . $path);
if (class_exists($classPath)) {
return $classPath;
}
throw new \InvalidArgumentException("{$path}는 올바른 API 경로가 아님");
}
function buildAPIExecutorClass($type, string $rootPath, array $args): \sammo\BaseAPI
{
$class = getAPIExecutorClass($type);
return new $class($rootPath, $args);
echo $e->getTraceAsString();
throw $e;
}
set_exception_handler('\\sammo\\logExceptionByCustomHandler');
+175 -164
View File
@@ -1,191 +1,202 @@
<?php
namespace sammo;
require(__DIR__ . '/../vendor/autoload.php');
require(__dir__.'/../vendor/autoload.php');
?>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>설치</title>
<?php /* NOTE: 설치 이전에는 ServConfig가 준비되어있지 않으므로 예외로 수동 지정 */ ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('../dist_js/gateway/vendors.js') ?>
<?= WebUtil::printCSS('../dist_js/gateway/vendor.css') ?>
<?= WebUtil::printJS('../dist_js/gateway/common_ts.js') ?>
<?= WebUtil::printCSS('../dist_js/gateway/common_ts.css') ?>
<?= WebUtil::printJS('../dist_js/gateway/install.js') ?>
<?= WebUtil::printCSS('../dist_js/gateway/install.css') ?>
<?= WebUtil::printCSS('../css/install.css') ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.validate.min.js')?>
<?=WebUtil::printJS('../e_lib/sha512.min.js')?>
<?=WebUtil::printJS('../js/common.js')?>
<?=WebUtil::printJS('../js/install.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../css/install.css')?>
</head>
<body>
<div class="container">
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe 설치</h1>
<div class="row justify-content-md-center">
<div class="col col-12 col-md-10 col-lg-7">
<div class="card" id="db_form_card" style="display:none">
<h3 class="card-header">
설치(DB 설정)
</h3>
<div class="card-body">
<form id="db_form" method="post" action="#">
<div class="form-group row">
<label for="db_host" class="col-sm-4 col-form-label">DB호스트</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_host" id="db_host" placeholder="호스트" value="localhost" />
</div>
</div>
<div class="form-group row">
<label for="db_port" class="col-sm-4 col-form-label">DB포트</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_port" id="db_port" placeholder="접속 포트" value="3306" />
</div>
</div>
<div class="form-group row">
<label for="db_id" class="col-sm-4 col-form-label">DB계정명</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_id" id="db_id" placeholder="DB계정" />
</div>
</div>
<div class="form-group row">
<label for="db_pw" class="col-sm-4 col-form-label">DB비밀번호</label>
<div class="col-sm-8">
<input type="password" class="form-control" name="db_pw" id="db_pw" placeholder="DB비밀번호" />
</div>
</div>
<div class="form-group row">
<label for="db_name" class="col-sm-4 col-form-label">DB명</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_name" id="db_name" placeholder="DB명(예:sammo)" />
</div>
</div>
<div class="form-group row">
<label for="serv_host" class="col-sm-4 col-form-label">접속 경로</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="serv_host" id="serv_host" placeholder="접속경로(예:http://www.example.com)" />
</div>
</div>
<div class="form-group row">
<label for="shared_icon_path" class="col-sm-4 col-form-label">공용 아이콘 주소</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="shared_icon_path" id="shared_icon_path" placeholder="공용 아이콘 주소(웹 주소, 또는 접속 경로에 따른 상대 주소)" value="../image/icons" />
</div>
</div>
<div class="form-group row">
<label for="game_image_path" class="col-sm-4 col-form-label">게임 이미지 주소</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="game_image_path" id="game_image_path" placeholder="게임 이미지 주소(웹 주소, 또는 접속 경로에 따른 상대 주소)" value="../image/game" />
</div>
</div>
<div class="form-group row">
<label for="image_request_key" class="col-sm-4 col-form-label">이미지 갱신 </label>
<div class="input-group col-sm-8">
<input type="text" class="form-control" name="image_request_key" id="image_request_key" placeholder="이미지 서버의 hook/HashKey.php의 값과 동일하게" value="" />
<div class="input-group-text">
<button id="btn_random_generate_key" class="btn btn-secondary" type="button">랜덤 생성</button>
</div>
</div>
</div>
<hr style="width:100%; border-top: 1px solid lightgray;">
<div class="form-group row">
<label for="kakao_rest_key" class="col-sm-4 col-form-label">카카오 API Rest Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_rest_key" id="kakao_rest_key" placeholder="카카오톡 API의 Rest Key" value="" />
</div>
</div>
<div class="form-group row">
<label for="kakao_admin_key" class="col-sm-4 col-form-label">카카오 API Admin Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_admin_key" id="kakao_admin_key" placeholder="카카오톡 API의 Admin Key" value="" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-4"></div>
<div class="col-sm-8">
<button type="submit" class="btn btn-primary btn-lg btn-block login-button">설정 파일 생성</button>
</div>
</div>
</form>
<div class="col col-12 col-md-10 col-lg-7">
<div class="card" id="db_form_card" style="display:none">
<h3 class="card-header">
설치(DB 설정)
</h3>
<div class="card-body">
<form id="db_form" method="post" action="#">
<div class="form-group row">
<label for="db_host" class="col-sm-4 col-form-label">DB호스트</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_host" id="db_host"
placeholder="호스트" value="localhost" />
</div>
</div>
</div>
<!--DB -->
<div class="card" id="admin_form_card" style="display:none">
<h3 class="card-header">
설치(관리자 생성)
</h3>
<div class="card-body">
<form id="admin_form" method="post" action="#">
<div class="form-group row">
<label for="username" class="col-sm-3 col-form-label">계정명</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="username" id="username" placeholder="계정명" />
</div>
</div>
<div class="form-group row">
<label for="password" class="col-sm-3 col-form-label">비밀번호</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="password" id="password" placeholder="비밀번호" />
</div>
</div>
<div class="form-group row">
<label for="confirm_password" class="col-sm-3 col-form-label">비밀번호 확인</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="비밀번호 확인" />
</div>
</div>
<div class="form-group row">
<label for="nickname" class="col-sm-3 col-form-label">닉네임</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="nickname" id="nickname" placeholder="닉네임" value="운영자" />
</div>
</div>
<input type="hidden" id="global_salt" name="global_salt">
<div class="form-group row">
<div class="col-sm-3"></div>
<div class="col-sm-9">
<button type="submit" class="btn btn-primary btn-lg btn-block login-button">관리자 계정 생성</button>
</div>
</div>
</form>
<div class="form-group row">
<label for="db_port" class="col-sm-4 col-form-label">DB포트</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_port" id="db_port"
placeholder="접속 포트" value="3306" />
</div>
</div>
<div class="form-group row">
<label for="db_id" class="col-sm-4 col-form-label">DB계정명</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_id" id="db_id" placeholder="DB계정"/>
</div>
</div>
</div>
<!--ADMIN -->
<!-- TODO: conf_kakao.php -->
<div class="form-group row">
<label for="db_pw" class="col-sm-4 col-form-label">DB비밀번호</label>
<div class="col-sm-8">
<input type="password" class="form-control" name="db_pw" id="db_pw"
placeholder="DB비밀번호"/>
</div>
</div>
<div class="form-group row">
<label for="db_name" class="col-sm-4 col-form-label">DB명</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_name" id="db_name"
placeholder="DB명(예:sammo)"/>
</div>
</div>
<div class="form-group row">
<label for="serv_host" class="col-sm-4 col-form-label">접속 경로</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="serv_host" id="serv_host"
placeholder="접속경로(예:http://www.example.com)"/>
</div>
</div>
<div class="form-group row">
<label for="shared_icon_path" class="col-sm-4 col-form-label">공용 아이콘 주소</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="shared_icon_path" id="shared_icon_path"
placeholder="공용 아이콘 주소(웹 주소, 또는 접속 경로에 따른 상대 주소)"
value="../image/icons" />
</div>
</div>
<div class="form-group row">
<label for="game_image_path" class="col-sm-4 col-form-label">게임 이미지 주소</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="game_image_path" id="game_image_path"
placeholder="게임 이미지 주소(웹 주소, 또는 접속 경로에 따른 상대 주소)"
value="../image/game" />
</div>
</div>
<div class="form-group row">
<label for="image_request_key" class="col-sm-4 col-form-label">이미지 갱신 </label>
<div class="input-group col-sm-8">
<input type="text" class="form-control" name="image_request_key" id="image_request_key"
placeholder="이미지 서버의 hook/HashKey.php의 값과 동일하게"
value="" />
<div class="input-group-append">
<button id="btn_random_generate_key" class="btn btn-secondary" type="button">랜덤 생성</button>
</div>
</div>
</div>
<hr style="width:100%; border-top: 1px solid lightgray;">
<div class="form-group row">
<label for="kakao_rest_key" class="col-sm-4 col-form-label">카카오 API Rest Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_rest_key" id="kakao_rest_key"
placeholder="카카오톡 API의 Rest Key"
value="" />
</div>
</div>
<div class="form-group row">
<label for="kakao_admin_key" class="col-sm-4 col-form-label">카카오 API Admin Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_admin_key" id="kakao_admin_key"
placeholder="카카오톡 API의 Admin Key"
value="" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-4"></div>
<div class="col-sm-8">
<button type="submit"
class="btn btn-primary btn-lg btn-block login-button">설정 파일 생성</button>
</div>
</div>
</form>
</div>
</div><!--DB -->
<div class="card" id="admin_form_card" style="display:none">
<h3 class="card-header">
설치(관리자 생성)
</h3>
<div class="card-body">
<form id="admin_form" method="post" action="#">
<div class="form-group row">
<label for="username" class="col-sm-3 col-form-label">계정명</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="username" id="username"
placeholder="계정명"/>
</div>
</div>
<div class="form-group row">
<label for="password" class="col-sm-3 col-form-label">비밀번호</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="password" id="password"
placeholder="비밀번호"/>
</div>
</div>
<div class="form-group row">
<label for="confirm_password" class="col-sm-3 col-form-label">비밀번호 확인</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="confirm_password" id="confirm_password"
placeholder="비밀번호 확인"/>
</div>
</div>
<div class="form-group row">
<label for="nickname" class="col-sm-3 col-form-label">닉네임</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="nickname" id="nickname"
placeholder="닉네임" value="운영자"/>
</div>
</div>
<input type="hidden" id="global_salt" name="global_salt">
<div class="form-group row">
<div class="col-sm-3"></div>
<div class="col-sm-9">
<button type="submit"
class="btn btn-primary btn-lg btn-block login-button">관리자 계정 생성</button>
</div>
</div>
</form>
</div>
</div><!--ADMIN -->
<!-- TODO: conf_kakao.php -->
</div>
</div>
</div>
</body>
</html>
</html>
+33 -34
View File
@@ -1,34 +1,33 @@
<?php
namespace sammo;
require(__DIR__ . '/../vendor/autoload.php');
require(__dir__.'/../vendor/autoload.php');
session_start();
session_destroy();
$username = mb_strtolower(Util::getPost('username'), 'utf-8');
$password = Util::getPost('password', 'string');
$nickname = Util::getPost('nickname');
$username = mb_strtolower(Util::getReq('username'), 'utf-8');
$password = Util::getReq('password', 'string');
$nickname = Util::getReq('nickname');
if (!$username || !$password || !$nickname) {
if(!$username || !$password || !$nickname){
Json::die([
'result' => false,
'reason' => '입력값이 설정되지 않았습니다.'
'result'=>false,
'reason'=>'입력값이 설정되지 않았습니다.'
]);
}
if (strlen((string) $password) != 128) {
if(strlen((string)$password)!=128){
Json::die([
'result' => false,
'reason' => '올바르지 않은 비밀번호 해시 포맷입니다.'
'result'=>false,
'reason'=>'올바르지 않은 비밀번호 해시 포맷입니다.'
]);
}
if (!class_exists('\\sammo\\RootDB')) {
if(!class_exists('\\sammo\\RootDB')){
Json::die([
'result' => false,
'reason' => 'DB 설정이 완료되지 않았습니다.'
'result'=>false,
'reason'=>'DB 설정이 완료되지 않았습니다.'
]);
}
@@ -38,43 +37,43 @@ $rootDB = RootDB::db();
$rootDB->query('LOCK TABLES member WRITE, member_log WRITE');
$memberCnt = $rootDB->queryFirstField('SELECT count(`NO`) from member');
if ($memberCnt > 0) {
if($memberCnt > 0){
Json::die([
'result' => 'false',
'reason' => '이미 계정이 생성되어 있습니다'
'result'=>'false',
'reason'=>'이미 계정이 생성되어 있습니다'
]);
}
$userSalt = bin2hex(random_bytes(8));
$finalPassword = Util::hashPassword($userSalt, $password);
$nowDate = TimeUtil::now();
$nowDate = TimeUtil::DatetimeNow();
$rootDB->insert('member', [
$rootDB->insert('member',[
'oauth_type' => 'NONE',
'id' => $username,
'email' => null,
'token_valid_until' => '2999-01-01 00:00:00',
'token_valid_until'=>'2999-01-01 00:00:00',
'pw' => $finalPassword,
'salt' => $userSalt,
'grade' => 6,
'name' => $nickname,
'reg_date' => $nowDate
'grade'=> 6,
'name'=>$nickname,
'reg_date'=>$nowDate
]);
$userID = $rootDB->insertId();
$rootDB->insert('member_log', [
'member_no' => $userID,
'date' => $nowDate,
'action_type' => 'reg',
'action' => Json::encode([
'type' => 'none',
'aux' => 'admin',
'id' => $username,
'name' => $nickname
'member_no'=>$userID,
'date'=>$nowDate,
'action_type'=>'reg',
'action'=>Json::encode([
'type'=>'none',
'aux'=>'admin',
'id'=>$username,
'name'=>$nickname
])
]);
Json::die([
'result' => true,
'reason' => 'success'
]);
'result'=>true,
'reason'=>'success'
]);
+12 -18
View File
@@ -1,44 +1,38 @@
<?php
namespace sammo;
if(!file_exists(__DIR__ . '/../vendor/autoload.php')){
http_response_code(503);
die('not_ready');
}
require(__dir__.'/../vendor/autoload.php');
require(__DIR__ . '/../vendor/autoload.php');
if (!class_exists('\\sammo\\RootDB')) {
if(!class_exists('\\sammo\\RootDB')){
Json::die([
'step' => 'config'
'step'=>'config'
]);
}
$rootDB = RootDB::db();
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
$rootDB->nonsql_error_handler = function($params){
Json::die([
'step' => 'conn_fail'
'step'=>'conn_fail'
]);
};
$rootDB->error_handler = function ($params) {
$rootDB->error_handler = function($params){
Json::die([
'step' => 'sql_fail'
'step'=>'sql_fail'
]);
};
$memberCnt = $rootDB->queryFirstField('SELECT count(`NO`) from member');
if ($memberCnt == 0) {
if($memberCnt == 0){
Json::die([
'step' => 'admin',
'globalSalt' => RootDB::getGlobalSalt()
'step'=>'admin',
'globalSalt'=>RootDB::getGlobalSalt()
]);
}
Json::die([
'step' => 'done'
]);
'step'=>'done'
]);
+303 -313
View File
@@ -1,313 +1,303 @@
<?php
namespace sammo;
require(__DIR__ . '/../vendor/autoload.php');
$host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id');
$password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name');
$servHost = Util::getPost('serv_host');
$sharedIconPath = Util::getPost('shared_icon_path');
$gameImagePath = Util::getPost('game_image_path');
$imageRequestKey = Util::getPost('image_request_key');
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([
'result' => false,
'reason' => '입력 값이 올바르지 않습니다'
]);
}
if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
Json::die([
'result' => false,
'reason' => '접속 경로가 올바르지 않습니다.'
]);
}
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
Json::die([
'result' => false,
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
]);
}
if (class_exists('\\sammo\\RootDB')) {
Json::die([
'result' => false,
'reason' => '이미 RootDB.php 파일이 있습니다'
]);
}
//파일 권한 검사
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
Json::die([
'result' => false,
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
Json::die([
'result' => false,
'reason' => 'd_log 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
Json::die([
'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
Json::die([
'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다'
]);
}
if (
!file_exists(ROOT . '/d_log')
|| !file_exists(ROOT . '/d_shared')
|| !file_exists(ROOT . '/d_setting')
|| !file_exists(AppConf::getUserIconPathFS())
) {
if (!is_writable(ROOT)) {
Json::die([
'result' => false,
'reason' => '하위 디렉토리 생성 권한이 없습니다'
]);
}
//기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS());
}
if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log');
}
if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting');
}
if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared');
}
}
if (!is_writable(AppConf::getUserIconPathFS())) {
Json::die([
'result' => false,
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_log')) {
Json::die([
'result' => false,
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_shared')) {
Json::die([
'result' => false,
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_setting')) {
Json::die([
'result' => false,
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
]);
}
if (!file_exists(ROOT . '/d_log/.htaccess')) {
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
}
if (!file_exists(ROOT . '/d_setting/.htaccess')) {
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
}
//DB 접근 권한 검사
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'DB 접속에 실패했습니다.'
]);
};
$rootDB->error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]);
};
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
while (true) {
if (!$mysqli_obj->more_results()) {
break;
}
if (!$mysqli_obj->next_result()) {
break;
}
}
}
$rootDB->insert('system', array(
'REG' => 'N',
'LOGIN' => 'N',
'CRT_DATE' => TimeUtil::now(),
'MDF_DATE' => TimeUtil::now()
));
$globalSalt = bin2hex(random_bytes(16));
'@phan-var-force string $servHost';
'@phan-var-force string $sharedIconPath';
'@phan-var-force string $gameImagePath';
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath,
'imageRequestPath' => $imageRequestPath,
'imageRequestKey' => $imageRequestKey,
'serverList' => [
['che', '체', 'white'],
['kwe', '퀘', 'yellow'],
['pwe', '풰', 'orange'],
['twe', '퉤', 'magenta'],
['nya', '냐', '#e67e22'],
['pya', '퍄', '#9b59b6']
]
],
true
);
if ($imageRequestKey) {
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
}
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common_path.orig.js',
ROOT . '/d_shared/common_path.js',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
],
true
);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/menu.orig.json',
ROOT . '/d_shared/menu.json',
[],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common.orig.css',
ROOT . '/d_shared/common.css',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/RootDB.orig.php',
ROOT . '/d_setting/RootDB.php',
[
'host' => $host,
'user' => $username,
'password' => $password,
'dbName' => $dbName,
'port' => $port,
'globalSalt' => $globalSalt,
]
);
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/KakaoKey.orig.php',
ROOT . '/d_setting/KakaoKey.php',
[
'REST_API_KEY' => $kakaoRESTKey,
'ADMIN_KEY' => $kakaoAdminKey,
'REDIRECT_URI' => $kakaoRedirectURI
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
Json::die([
'result' => true,
'reason' => 'success',
'globalSalt' => $globalSalt
]);
<?php
namespace sammo;
require(__dir__.'/../vendor/autoload.php');
$host = Util::getReq('db_host');
$port = Util::getReq('db_port', 'int');
$username = Util::getReq('db_id');
$password = Util::getReq('db_pw');
$dbName = Util::getReq('db_name');
$servHost = Util::getReq('serv_host');
$sharedIconPath = Util::getReq('shared_icon_path');
$gameImagePath = Util::getReq('game_image_path');
$imageRequestKey = Util::getReq('image_request_key');
$kakaoRESTKey = Util::getReq('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getReq('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([
'result'=>false,
'reason'=>'입력 값이 올바르지 않습니다'
]);
}
if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
Json::die([
'result'=>false,
'reason'=>'접속 경로가 올바르지 않습니다.'
]);
}
if (file_exists(ROOT.'/d_setting/RootDB.php') && is_dir(ROOT.'/d_setting/RootDB.php')) {
Json::die([
'result'=>false,
'reason'=>'d_setting/RootDB.php 가 디렉토리입니다'
]);
}
if (class_exists('\\sammo\\RootDB')) {
Json::die([
'result'=>false,
'reason'=>'이미 RootDB.php 파일이 있습니다'
]);
}
//파일 권한 검사
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
Json::die([
'result'=>false,
'reason'=>AppConf::$userIconPath.' 이 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT.'/d_log') && !is_dir(ROOT.'/d_log')) {
Json::die([
'result'=>false,
'reason'=>'d_log 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT.'/d_shared') && !is_dir(ROOT.'/d_shared')) {
Json::die([
'result'=>false,
'reason'=>'d_shared 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT.'/d_setting') && !is_dir(ROOT.'/d_setting')) {
Json::die([
'result'=>false,
'reason'=>'d_shared 가 디렉토리가 아닙니다'
]);
}
if (!file_exists(ROOT.'/d_log')
|| !file_exists(ROOT.'/d_shared')
|| !file_exists(ROOT.'/d_setting')
|| !file_exists(AppConf::getUserIconPathFS())
) {
if (!is_writable(ROOT)) {
Json::die([
'result'=>false,
'reason'=>'하위 디렉토리 생성 권한이 없습니다'
]);
}
//기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS());
}
if (!file_exists(ROOT.'/d_log')) {
mkdir(ROOT.'/d_log');
}
if (!file_exists(ROOT.'/d_setting')) {
mkdir(ROOT.'/d_setting');
}
if (!file_exists(ROOT.'/d_shared')) {
mkdir(ROOT.'/d_shared');
}
}
if (!is_writable(AppConf::getUserIconPathFS())) {
Json::die([
'result'=>false,
'reason'=>AppConf::$userIconPath.' 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT.'/d_log')) {
Json::die([
'result'=>false,
'reason'=>'d_log 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT.'/d_shared')) {
Json::die([
'result'=>false,
'reason'=>'d_shared 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT.'/d_setting')) {
Json::die([
'result'=>false,
'reason'=>'d_setting 디렉토리의 쓰기 권한이 없습니다.'
]);
}
if (!file_exists(ROOT.'/d_log/.htaccess')) {
@file_put_contents(ROOT.'/d_log/.htaccess', 'Deny from all');
}
if (!file_exists(ROOT.'/d_setting/.htaccess')) {
@file_put_contents(ROOT.'/d_setting/.htaccess', 'Deny from all');
}
//DB 접근 권한 검사
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([
'result'=>false,
'reason'=>'DB 접속에 실패했습니다.'
]);
};
$rootDB->error_handler = function ($params) {
Json::die([
'result'=>false,
'reason'=>'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]);
};
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
if ($mysqli_obj->multi_query(file_get_contents(__dir__.'/sql/common_schema.sql'))) {
while (true) {
if (!$mysqli_obj->more_results()) {
break;
}
if (!$mysqli_obj->next_result()) {
break;
}
}
}
$rootDB->insert('system', array(
'REG' => 'N',
'LOGIN' => 'N',
'CRT_DATE' => TimeUtil::DatetimeNow(),
'MDF_DATE' => TimeUtil::DatetimeNow()
));
$globalSalt = bin2hex(random_bytes(16));
'@phan-var-force string $servHost';
'@phan-var-force string $sharedIconPath';
'@phan-var-force string $gameImagePath';
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath.'/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath.'/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/ServConfig.orig.php',
ROOT.'/d_setting/ServConfig.php',
[
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath,
'imageRequestPath'=>$imageRequestPath,
'imageRequestKey'=>$imageRequestKey
],
true
);
if($imageRequestKey){
@file_get_contents($imageKeyInstallPath.'?key='.$imageRequestKey);
}
if ($result !== true) {
Json::die([
'result'=>false,
'reason'=>$result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/common_path.orig.js',
ROOT.'/d_shared/common_path.js',
[
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
],
true
);
$result = Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/menu.orig.json',
ROOT.'/d_shared/menu.json',
[],
true
);
if ($result !== true) {
Json::die([
'result'=>false,
'reason'=>$result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/common.orig.css',
ROOT.'/d_shared/common.css',
[
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result'=>false,
'reason'=>$result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/RootDB.orig.php',
ROOT.'/d_setting/RootDB.php',
[
'host'=>$host,
'user'=>$username,
'password'=>$password,
'dbName'=>$dbName,
'port'=>$port,
'globalSalt'=>$globalSalt,
]
);
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost.'/');
Util::generateFileUsingSimpleTemplate(
__dir__.'/templates/KakaoKey.orig.php',
ROOT.'/d_setting/KakaoKey.php',
[
'REST_API_KEY'=>$kakaoRESTKey,
'ADMIN_KEY'=>$kakaoAdminKey,
'REDIRECT_URI'=>$kakaoRedirectURI
],
true
);
if ($result !== true) {
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success',
'globalSalt'=>$globalSalt
]);
+47 -44
View File
@@ -1,26 +1,25 @@
<?php
namespace sammo;
require(__DIR__ . '/../vendor/autoload.php');
require(__dir__.'/../vendor/autoload.php');
$session = Session::requireLogin([])->setReadOnly();
if ($session->userGrade < 6) {
if($session->userGrade < 6){
Json::die([
'result' => false,
'reason' => '관리자 아님'
'result'=>false,
'reason'=>'관리자 아님'
]);
}
$servHost = Util::getPost('serv_host');
$sharedIconPath = Util::getPost('shared_icon_path');
$gameImagePath = Util::getPost('game_image_path');
$servHost = Util::getReq('serv_host');
$sharedIconPath = Util::getReq('shared_icon_path');
$gameImagePath = Util::getReq('game_image_path');
if ($servHost) {
if (!$sharedIconPath || $gameImagePath) {
if($servHost){
if(!$sharedIconPath || $gameImagePath){
Json::die([
'result' => false,
'reason' => 'serv_host가 지정된 경우, sharedIconPath와 gameImagePath가 모두 지정되어야합니다.'
'result'=>false,
'reason'=>'serv_host가 지정된 경우, sharedIconPath와 gameImagePath가 모두 지정되어야합니다.'
]);
}
@@ -28,54 +27,58 @@ if ($servHost) {
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php',
__dir__.'/templates/ServConfig.orig.php',
ROOT.'/d_setting/ServConfig.php',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
'result'=>false,
'reason'=>$result
]);
}
} else if ($sharedIconPath || $gameImagePath) {
}
else if($sharedIconPath || $gameImagePath){
$servHost = ServConfig::$serverWebPath;
if ($sharedIconPath) {
if($sharedIconPath){
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
} else {
}
else{
$sharedIconPath = ServConfig::$sharedIconPath;
}
if ($gameImagePath) {
if($gameImagePath){
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
} else {
}
else{
$gameImagePath = ServConfig::$gameImagePath;
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php',
__dir__.'/templates/ServConfig.orig.php',
ROOT.'/d_setting/ServConfig.php',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
'result'=>false,
'reason'=>$result
]);
}
} else {
}
else{
$servHost = ServConfig::$serverWebPath;
$sharedIconPath = ServConfig::$sharedIconPath;
$gameImagePath = ServConfig::$gameImagePath;
@@ -84,31 +87,31 @@ if ($servHost) {
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common_path.orig.js',
ROOT . '/d_shared/common_path.js',
__dir__.'/templates/common_path.orig.js',
ROOT.'/d_shared/common_path.js',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
],
true
);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common.orig.css',
ROOT . '/d_shared/common.css',
__dir__.'/templates/common.orig.css',
ROOT.'/d_shared/common.css',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
'serverBasePath'=>$servHost,
'sharedIconPath'=>$sharedIconPath,
'gameImagePath'=>$gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
'result'=>false,
'reason'=>$result
]);
}
+10 -30
View File
@@ -14,7 +14,7 @@ CREATE TABLE `system` (
`MDF_DATE` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`NO`)
)
ENGINE=Aria DEFAULT CHARSET=utf8mb4;
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 회원 테이블
CREATE TABLE `member` (
@@ -31,8 +31,8 @@ CREATE TABLE `member` (
`NAME` VARCHAR(64) NOT NULL,
`PICTURE` VARCHAR(64) NULL DEFAULT 'default.jpg',
`IMGSVR` INT(1) NULL DEFAULT '0',
`acl` TEXT NOT NULL DEFAULT '{}' COLLATE 'utf8mb4_bin',
`penalty` TEXT NOT NULL DEFAULT '{}' COLLATE 'utf8mb4_bin',
`acl` TEXT NOT NULL DEFAULT '{}' COMMENT 'json',
`penalty` TEXT NOT NULL DEFAULT '{}' COMMENT 'json',
`GRADE` INT(1) NULL DEFAULT '1',
`REG_NUM` INT(3) NULL DEFAULT '0',
`REG_DATE` DATETIME NOT NULL,
@@ -43,12 +43,9 @@ CREATE TABLE `member` (
UNIQUE INDEX `ID` (`ID`),
UNIQUE INDEX `EMAIL` (`EMAIL`),
UNIQUE INDEX `kauth_id` (`oauth_id`),
INDEX `delete_after` (`delete_after`),
CONSTRAINT `json1` CHECK (json_valid(`acl`)),
CONSTRAINT `json2` CHECK (json_valid(`penalty`))
INDEX `delete_after` (`delete_after`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria;
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 로그인 로그 테이블
CREATE TABLE `member_log` (
@@ -56,14 +53,12 @@ CREATE TABLE `member_log` (
`member_no` INT(11) NOT NULL,
`date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`action_type` ENUM('reg','try_login','login','logout','oauth','change_pw','make_general','access_server','delete') NOT NULL,
`action` TEXT NULL DEFAULT NULL COLLATE 'utf8mb4_bin',
`action` TEXT NULL DEFAULT NULL COMMENT 'JSON',
PRIMARY KEY (`id`),
INDEX `action` (`member_no`, `action_type`, `date`),
INDEX `member` (`member_no`, `date`),
CONSTRAINT `json` CHECK (json_valid(`action`))
INDEX `member` (`member_no`, `date`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria;
ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
###################
# KV storage
@@ -74,22 +69,7 @@ CREATE TABLE if not exists `storage` (
`key` VARCHAR(40) NOT NULL,
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `key` (`namespace`, `key`),
CONSTRAINT `json` CHECK (json_valid(`value`))
)
COLLATE='utf8mb4_bin'
ENGINE=Aria;
CREATE TABLE `login_token` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`base_token` VARCHAR(20) NOT NULL COLLATE 'utf8mb4_general_ci',
`reg_ip` VARCHAR(40) NOT NULL COLLATE 'utf8mb4_general_ci',
`reg_date` DATETIME NOT NULL,
`expire_date` DATETIME NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `by_token` (`base_token`),
INDEX `by_date` (`user_id`, `expire_date`)
UNIQUE INDEX `key` (`namespace`, `key`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=Aria;
ENGINE=MyISAM
-1
View File
@@ -1,7 +1,6 @@
<?php
namespace kakao;
// @suppress PhanRedefineClass
class KakaoKey{
const REST_KEY = '_tK_REST_API_KEY_';
const ADMIN_KEY = '_tK_ADMIN_KEY_';
+1 -34
View File
@@ -1,16 +1,9 @@
<?php
namespace sammo;
//https://hub.packtpub.com/eloquent-without-laravel/
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
class RootDB
{
private static $uDB = null;
private static ?Capsule $uIlluminate = null;
private static $host = '_tK_host_';
private static $user = '_tK_user_';
@@ -18,8 +11,6 @@ class RootDB
private static $dbName = '_tK_dbName_';
private static $port = _tK_port_;
private static $encoding = 'utf8mb4';
private static $collation = 'utf8mb4_general_ci';
private static $globalSalt = '_tK_globalSalt_';
@@ -27,29 +18,6 @@ class RootDB
{
}
public static function illuminate(): Capsule
{
if(self::$uIlluminate !== null){
return self::$uIlluminate;
}
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => self::$host,
'database' => self::$dbName,
'username' => self::$user,
'password' => self::$password,
'charset' => self::$encoding,
'collation' => self::$collation,
], 'root');
$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->bootEloquent();
self::$uIlluminate = $capsule;
return $capsule;
}
/**
* DB 객체 생성
*
@@ -62,8 +30,7 @@ class RootDB
self::$uDB = new \MeekroDB(self::$host, self::$user, self::$password, self::$dbName, self::$port, self::$encoding);
self::$uDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
self::$uDB->error_handler = function () {
};
self::$uDB->error_handler= function(){};
self::$uDB->throw_exception_on_error = true;
self::$uDB->throw_exception_on_nonsql_error = true;
}
+54 -74
View File
@@ -1,74 +1,54 @@
<?php
namespace sammo;
class ServConfig
{
private function __construct()
{
}
public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_';
private static $serverList = null;
public static function getSharedIconPath(string $filepath = ''): string
{
if ($filepath) {
return static::$sharedIconPath . "/{$filepath}";
}
return static::$sharedIconPath;
}
public static function getUserIconPath(string $filepath = ''): string
{
return AppConf::getUserIconPathWeb($filepath);
}
public static function getGameImagePath(string $filepath = ''): string
{
if ($filepath) {
return static::$gameImagePath . "/{$filepath}";
}
return static::$gameImagePath;
}
public static function getImagePullURI(): string
{
$now = time();
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
}
/**
* 서버 설정 반환
*
* @return \sammo\Setting[]
*/
public static function getServerList(): array{
$servKeyList = [/*_tK_serverList_*/];
$servKeyList[] = ['hwe', '훼', 'red'];
if (self::$serverList === null) {
self::$serverList = [];
foreach($servKeyList as [$servKey, $servNick, $servColor]){
self::$serverList[$servKey] = new Setting(ROOT.'/'.$servKey, $servNick, $servColor);
}
}
return self::$serverList;
}
/**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
*
* @return string
*/
public static function getServerBasepath(): string
{
return self::$serverWebPath;
}
}
<?php
namespace sammo;
class ServConfig
{
private function __construct()
{
}
public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_';
public static function getSharedIconPath(string $filepath='') : string
{
if($filepath){
return static::$sharedIconPath."/{$filepath}";
}
return static::$sharedIconPath;
}
public static function getUserIconPath(string $filepath='') : string
{
return AppConf::getUserIconPathWeb($filepath);
}
public static function getGameImagePath(string $filepath='') : string
{
if($filepath){
return static::$gameImagePath."/{$filepath}";
}
return static::$gameImagePath;
}
public static function getImagePullURI() : string
{
$now = time();
$req_hash = Util::hashPassword(sprintf("%016x",$now), static::$imageRequestKey);
return static::$imageRequestPath."?req={$req_hash}&time={$now}";
}
/**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
*
* @return string
*/
public static function getServerBasepath() : string
{
return self::$serverWebPath;
}
}
+11 -66
View File
@@ -6,33 +6,38 @@
.img_back {background-image:url('_tK_gameImagePath_/back.jpg'); }
/* 레거시. */
#bg0 { background-image:url('_tK_gameImagePath_/back_walnut.jpg'); }
#bg1 { background-image:url('_tK_gameImagePath_/back_green.jpg'); }
#bg2 { background-image:url('_tK_gameImagePath_/back_blue.jpg'); }
.map_detail .map_title{
background:
url('_tK_gameImagePath_/ltitle.jpg') no-repeat left,
url('_tK_gameImagePath_/ltitle.jpg') no-repeat left,
url('_tK_gameImagePath_/rtitle.jpg') no-repeat right;
}
.map_detail.map_spring .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/spring.gif') no-repeat right;
}
.map_detail.map_summer .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/summer.gif') no-repeat right;
}
.map_detail.map_fall .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/fall.gif') no-repeat right;
}
.map_detail.map_winter .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/winter.gif') no-repeat right;
}
@@ -83,59 +88,6 @@
background-size: 700px 500px;
}
/*미니체 지도*/
.map_theme_miniche_b.map_spring .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_spring.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_b.map_summer .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_summer.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_b.map_fall .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_fall.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_b.map_winter .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_winter.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_b .map_bgroad{
background: url('_tK_gameImagePath_/map/che/miniche_road.png') no-repeat;
background-size: 700px 500px;
}
/*미니체 지도*/
.map_theme_miniche_clean.map_spring .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_spring.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_clean.map_summer .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_summer.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_clean.map_fall .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_fall.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_clean.map_winter .map_bglayer1{
background: url('_tK_gameImagePath_/map/che/bg_winter.jpg') no-repeat;
background-size: 700px 500px;
}
.map_theme_miniche_clean .map_bgroad{
background: url('_tK_gameImagePath_/map/che/miniche_road.png') no-repeat;
background-size: 700px 500px;
}
/*루드라사움 지도*/
.map_theme_ludo_rathowm .map_bglayer1{
background: url('_tK_gameImagePath_/map/ludo_rathowm/back.jpg') no-repeat;
@@ -157,11 +109,4 @@
.map_theme_chess .map_bglayer1{
background: url('_tK_gameImagePath_/map/chess/chessboard.png') no-repeat;
background-size: 700px 500px;
}
/*포켓몬 v1 지도*/
.map_theme_pokemon_v1 .map_bglayer1{
background: url('_tK_gameImagePath_/map/pokemon_v1/back_pal8.png') no-repeat;
background-size: 700px 500px;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace sammo;
function MYDB_query($query, $connect)
{
return mysqli_query($connect, $query);
}
function MYDB_num_rows(\mysqli_result $result) : int
{
return mysqli_num_rows($result);
}
/**
* @return mixed[]
*/
function MYDB_fetch_array(\mysqli_result $result)
{
return mysqli_fetch_array($result);
}
function MYDB_fetch_row(\mysqli_result $result)
{
return mysqli_fetch_row($result);
}
function MYDB_error($connect)
{
return mysqli_error($connect);
}
+25 -5
View File
@@ -6,15 +6,35 @@ include "func.php";
$session = Session::requireGameLogin()->setReadOnly();
if($session->userGrade < 4) {
die(requireAdminPermissionHTML());
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
관리자가 아닙니다.<br>
<?=banner()?>
</body>
</html>
<?php
exit();
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
[$turntime, $tnmt_time] = $gameStor->getValuesAsArray(['turntime','tnmt_time']);
$plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
$query = "select plock from plock";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$plock = MYDB_fetch_array($result);
?>
<!DOCTYPE html>
<html>
@@ -24,15 +44,15 @@ $plock = $db->queryFirstField('SELECT plock FROM plock WHERE `type` ="GAME"');
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<form action=_119_b.php method=post>
시간조정 : <input type=text size=3 name=minute><input type=submit name=btn value='분당김'><input type=submit name=btn value='분지연'> 최종갱신 : <?=$turntime?><br>
시간조정 : <input type=text size=3 name=minute2><input type=submit name=btn value='토너분당김'><input type=submit name=btn value='토너분지연'> 토너먼트 : <?=$tnmt_time?><br>
봉급지급 : <input type=submit name=btn value='금지급'><input type=submit name=btn value='쌀지급'><br>
: <input type=submit name=btn value='락걸기'><input type=submit name=btn value='락풀기'> 현재 : <?=$plock>0?"동결중":"가동중"?><br>
: <input type=submit name=btn value='락걸기'><input type=submit name=btn value='락풀기'> 현재 : <?=$plock['plock']>0?"동결중":"가동중"?><br>
</form>
</body>
</html>
+61 -89
View File
@@ -1,5 +1,4 @@
<?php
namespace sammo;
include "lib.php";
@@ -7,7 +6,7 @@ include "func.php";
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 4) {
if($session->userGrade < 4){
header('location:_119.php');
die();
}
@@ -17,102 +16,75 @@ $v->rule('integer', [
'minute',
'minutes2'
]);
if (!$v->validate()) {
if(!$v->validate()){
Error($v->errorStr());
}
$btn = Util::getPost('btn');
$minute = Util::getPost('minute', 'int');
$minute2 = Util::getPost('minute2', 'int');
$btn = Util::getReq('btn');
$minute = Util::getReq('minute', 'int');
$minute2 = Util::getReq('minute2', 'int');
extractMissingPostToGlobals();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
switch ($btn) {
case "분당김":
$locked = false;
for ($i = 0; $i < 10; $i++) {
if (tryLock()) {
$locked = true;
break;
}
usleep(500000);
}
switch($btn) {
case "분당김":
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
$turntime = (new \DateTimeImmutable($gameStor->turntime))->sub(new \DateInterval("PT{$minute}M"));
$starttime = (new \DateTimeImmutable($gameStor->starttime))->sub(new \DateInterval("PT{$minute}M"));
$tnmt_time = (new \DateTimeImmutable($gameStor->tnmt_time))->sub(new \DateInterval("PT{$minute}M"));
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
$turntime = (new \DateTimeImmutable($gameStor->turntime))->sub(new \DateInterval("PT{$minute}M"));
$starttime = (new \DateTimeImmutable($gameStor->starttime))->sub(new \DateInterval("PT{$minute}M"));
$tnmt_time = (new \DateTimeImmutable($gameStor->tnmt_time))->sub(new \DateInterval("PT{$minute}M"));
$gameStor->turntime = $turntime->format('Y-m-d H:i:s');
$gameStor->starttime = $starttime->format('Y-m-d H:i:s');
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
$gameStor->turntime = $turntime->format('Y-m-d H:i:s.u');
$gameStor->starttime = $starttime->format('Y-m-d H:i:s');
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
$db->update('general', [
'turntime'=>$db->sqleval('DATE_SUB(turntime, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('auction', [
'expire'=>$db->sqleval('DATE_SUB(expire, INTERVAL %i MINUTE)', $minute)
], true);
break;
case "분지연":
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
$turntime = (new \DateTimeImmutable($gameStor->turntime))->add(new \DateInterval("PT{$minute}M"));
$starttime = (new \DateTimeImmutable($gameStor->starttime))->add(new \DateInterval("PT{$minute}M"));
$tnmt_time = (new \DateTimeImmutable($gameStor->tnmt_time))->add(new \DateInterval("PT{$minute}M"));
$db->update('general', [
'turntime' => $db->sqleval('DATE_SUB(turntime, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('ng_auction', [
'close_date' => $db->sqleval('DATE_SUB(close_date, INTERVAL %i MINUTE)', $minute)
], 'finished = 0');
if ($locked) {
unlock();
}
break;
case "분지연":
$locked = false;
for ($i = 0; $i < 5; $i++) {
if (tryLock()) {
$locked = true;
break;
}
usleep(500000);
}
$gameStor->cacheValues(['turntime', 'starttime', 'tnmt_time']);
$turntime = (new \DateTimeImmutable($gameStor->turntime))->add(new \DateInterval("PT{$minute}M"));
$starttime = (new \DateTimeImmutable($gameStor->starttime))->add(new \DateInterval("PT{$minute}M"));
$tnmt_time = (new \DateTimeImmutable($gameStor->tnmt_time))->add(new \DateInterval("PT{$minute}M"));
$gameStor->turntime = $turntime->format('Y-m-d H:i:s');
$gameStor->starttime = $starttime->format('Y-m-d H:i:s');
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
$gameStor->turntime = $turntime->format('Y-m-d H:i:s.u');
$gameStor->starttime = $starttime->format('Y-m-d H:i:s');
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
$db->update('general', [
'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('ng_auction', [
'close_date' => $db->sqleval('DATE_ADD(close_date, INTERVAL %i MINUTE)', $minute)
], 'finished = 0');
if ($locked) {
unlock();
}
break;
case "토너분당김":
$tnmt_time = new \DateTime($gameStor->tnmt_time);
$tnmt_time->sub(new \DateInterval("PT{$minute2}M"));
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
break;
case "토너분지연":
$tnmt_time = new \DateTimeImmutable($gameStor->tnmt_time);
$tnmt_time->add(new \DateInterval("PT{$minute2}M"));
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
break;
case "금지급":
processGoldIncome();
break;
case "쌀지급":
processRiceIncome();
break;
case "락걸기":
for ($i = 0; $i < 10; $i++) {
if (tryLock()) {
$locked = true;
break;
}
usleep(500000);
}
break;
case "락풀기":
unlock();
break;
$db->update('general', [
'turntime'=>$db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute)
], true);
$db->update('auction', [
'expire'=>$db->sqleval('DATE_ADD(expire, INTERVAL %i MINUTE)', $minute)
], true);
break;
case "토너분당김":
$tnmt_time = new \DateTime($gameStor->tnmt_time);
$tnmt_time->sub(new \DateInterval("PT{$minute2}M"));
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
break;
case "토너분지연":
$tnmt_time = new \DateTimeImmutable($gameStor->tnmt_time);
$tnmt_time->add(new \DateInterval("PT{$minute2}M"));
$gameStor->tnmt_time = $tnmt_time->format('Y-m-d H:i:s');
break;
case "금지급":
processGoldIncome();
break;
case "쌀지급":
processRiceIncome();
break;
case "락걸기":
$db->update('plock', ['plock'=>1], true);
break;
case "락풀기":
$db->update('plock', ['plock'=>0], true);
break;
}
header('Location:_119.php', true, 303);
header('Location:_119.php', true, 303);
+27 -4
View File
@@ -7,10 +7,28 @@ include "func.php";
$session = Session::requireGameLogin()->setReadOnly();
if($session->userGrade < 5) {
die(requireAdminPermissionHTML());
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
관리자가 아닙니다.<br>
<?=banner()?>
</body>
</html>
<?php
exit();
}
$db = DB::db();
$connect=$db->get();
$admin = getAdmin();
?>
@@ -22,8 +40,7 @@ $admin = getAdmin();
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class="tb_layout bg0">
@@ -39,7 +56,7 @@ $admin = getAdmin();
</tr>
<tr>
<td width=110 align=right>시작시간변경</td>
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime'], 0, 19)?>'><input type=submit name=btn value=변경1></td>
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=$admin['starttime']?>'><input type=submit name=btn value=변경1></td>
<td width=110 align=right>현재도시훈사</td>
<td width=285><?=$admin['city_rate']?></td>
</tr>
@@ -49,6 +66,12 @@ $admin = getAdmin();
<td width=110 align=right>최대 국가</td>
<td width=285><input type=text size=3 maxlength=2 style=color:white;background-color:black;text-align:right; name=maxnation value=<?=$admin['maxnation']?>><input type=submit name=btn value=변경3></td>
</tr>
<tr>
<td width=110 align=right></td>
<td width=285></td>
<td width=110 align=right>현재 수입률</td>
<td width=285><?=$admin['gold_rate']?>%</td>
</tr>
<tr>
<td width=110 align=right>시작 년도</td>
<td width=285><input type=text size=3 maxlength=3 style=color:white;background-color:black;text-align:right; name=startyear value='<?=$admin['startyear']?>'><input type=submit name=btn value=변경4></td>
+45 -28
View File
@@ -22,16 +22,19 @@ if (!$v->validate()) {
Error($v->errorStr());
}
$msg = Util::getPost('msg');
$btn = Util::getPost('btn');
$log = Util::getPost('log');
$starttime = Util::getPost('starttime', 'string', (new \DateTime())->format('Y-m-d H:i:s'));
$maxgeneral = Util::getPost('maxgeneral', 'int', GameConst::$defaultMaxGeneral);
$maxnation = Util::getPost('maxnation', 'int', GameConst::$defaultMaxNation);
$startyear = Util::getPost('startyear', 'int', GameConst::$defaultStartYear);
$msg = Util::getReq('msg');
$btn = Util::getReq('btn');
$log = Util::getReq('log');
$starttime = Util::getReq('starttime', 'string', (new \DateTime())->format('Y-m-d H:i:s'));
$maxgeneral = Util::getReq('maxgeneral', 'int', GameConst::$defaultMaxGeneral);
$maxnation = Util::getReq('maxnation', 'int', GameConst::$defaultMaxNation);
$startyear = Util::getReq('startyear', 'int', GameConst::$defaultStartYear);
extractMissingPostToGlobals();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$admin = getAdmin();
@@ -40,7 +43,11 @@ switch ($btn) {
$gameStor->msg = $msg;
break;
case "로그쓰기":
pushGlobalHistoryLog(["<R>★</><S>{$log}</>"]);
$lognum = $admin['historyindex'] + 1;
if ($lognum >= 29) {
$lognum = 0;
}
pushWorldHistory(["<R>★</><S>{$log}</>"]);
break;
case "변경1":
$gameStor->starttime = (new \DateTime($starttime))->format('Y-m-d H:i:s');
@@ -62,7 +69,6 @@ switch ($btn) {
case "30분턴":
case "60분턴":
case "120분턴":
$admin = $gameStor->getValues(['turntime', 'turnterm', 'year', 'startyear', 'month']);
switch ($btn) {
case "1분턴": $turnterm = 1; break;
case "2분턴": $turnterm = 2; break;
@@ -72,30 +78,41 @@ switch ($btn) {
case "30분턴": $turnterm = 30; break;
case "60분턴": $turnterm = 60; break;
case "120분턴": $turnterm = 120; break;
default: throw new \Exception("알 수 없는 턴 기간");
}
$oldunit = $admin['turnterm'] * 60;
$unit = $turnterm * 60;
$unitDiff = $unit / $oldunit;
$servTurnTime = new \DateTimeImmutable($admin['turntime']);
foreach ($db->query('SELECT no,turntime FROM general') as $gen) {
$genTurnTime = new \DateTimeImmutable($gen['turntime']);
$timeDiff = TimeUtil::DateIntervalToSeconds($genTurnTime->diff($servTurnTime));
$timeDiff *= $unitDiff;
$newGenTurnTime = $servTurnTime->add(TimeUtil::secondsToDateInterval($timeDiff));
$db->update('general', [
'turntime'=>$newGenTurnTime->format('Y-m-d H:i:s.u')
], 'no=%i', $gen['no']);
}
$turn = ($admin['year'] - $admin['startyear']) * 12 + $admin['month'] - 1;
$starttime = $servTurnTime->sub(TimeUtil::secondsToDateInterval($turn * $unit))->format('Y-m-d H:i:s');
$starttime = cutTurn($starttime, $turnterm, false);
$starttime = date("Y-m-d H:i:s", strtotime($admin['turntime']) - $turn * $unit);
$starttime = cutTurn($starttime, $turnterm);
$gameStor->turnterm = $turnterm;
$gameStor->starttime = $starttime;
pushGlobalHistoryLog(["<R>★</>턴시간이 <C>$btn</>으로 변경됩니다."]);
// 턴시간이 길어지는 경우 랜덤턴 배정
if ($turnterm < $admin['turnterm']) {
$query = "select no from general";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
$count = MYDB_num_rows($result);
for ($i=0; $i < $count; $i++) {
$gen = MYDB_fetch_array($result);
$turntime = getRandTurn($turnterm);
$query = "update general set turntime='$turntime' where no='{$gen['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
}
// 턴시간이 너무 멀리 떨어진 선수 제대로 보정
} else {
$query = "select no,turntime from general";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
$count = MYDB_num_rows($result);
for ($i=0; $i < $count; $i++) {
$gen = MYDB_fetch_array($result);
$num = intdiv((strtotime($gen['turntime']) - strtotime($admin['turntime'])), $unit);
if ($num > 0) {
$gen['turntime'] = date("Y-m-d H:i:s", strtotime($gen['turntime']) - $unit * $num);
$query = "update general set turntime='{$gen['turntime']}' where no='{$gen['no']}'";
MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect), "");
}
}
}
pushWorldHistory(["<R>★</>턴시간이 <C>$btn</>으로 변경됩니다."]);
break;
}
+112 -89
View File
@@ -1,5 +1,4 @@
<?php
namespace sammo;
include "lib.php";
@@ -7,8 +6,25 @@ include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 5) {
die(requireAdminPermissionHTML());
if($session->userGrade < 5) {
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
관리자가 아닙니다.<br>
<?=banner()?>
</body>
</html>
<?php
exit();
}
$db = DB::db();
@@ -16,96 +32,103 @@ $db = DB::db();
?>
<!DOCTYPE html>
<html>
<head>
<title>회원관리</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<title>회원관리</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td> <br><?= backButton() ?></td>
</tr>
</table>
<form name=form1 method=post action=_admin2_submit.php>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center>접속제한</td>
<td width=713 align=center><input type=submit name=btn value='전체 접속허용'><input type=submit name=btn value='전체 접속제한'></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center rowspan=12>회원선택<br><br>
<font color=cyan>NPC</font><br>
<font color=skyblue>NPC유저</font><br>
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
</td>
<td width=105 rowspan=12>
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>
<?php
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=backButton()?></td></tr>
</table>
<form name=form1 method=post action=_admin2_submit.php>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center>접속제한</td>
<td width=713 align=center><input type=submit name=btn value='전체 접속허용'><input type=submit name=btn value='전체 접속제한'></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center rowspan=12>회원선택<br><br><font color=cyan>NPC</font><br><font color=skyblue>NPC유저</font><br><font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b></td>
<td width=105 rowspan=12>
<?php
foreach ($generalList as $general) {
$style = "style=;";
if ($general['block'] > 0) {
$style .= "background-color:red;";
}
echo "
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:13px'>";
$generalList = $db->query('SELECT `no`, `name`, npc, `block` FROM general ORDER BY npc, binary(`name`)');
$npcColor = getNPCColor($general['npc']);
if ($npcColor !== null) {
$style .= "color:{$npcColor};";
}
foreach($generalList as $general){
$style = "style=;";
if($general['block'] > 0) { $style .= "background-color:red;"; }
if($general['npc'] >= 2) { $style .= "color:cyan;"; }
elseif($general['npc'] == 1) { $style .= "color:skyblue;"; }
echo "<option value={$general['no']} $style>{$general['name']}</option>";
}
?>
</select>
</td>
</tr>
<tr>
<td width=100 align=center>블럭</td>
<td width=504>
<input type=submit name=btn value='블럭 해제'><input type=submit name=btn value='1단계 블럭'><input type=submit name=btn value='2단계 블럭'><input type=submit name=btn value='3단계 블럭'><input type=submit name=btn value='무한삭턴'><br>
1단계:발언권, 2단계:턴블럭
</td>
</tr>
<tr>
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>이벤트2</td>
<td><input type=submit name=btn value='보숙10000'><input type=submit name=btn value='궁숙10000'><input type=submit name=btn value='기숙10000'><input type=submit name=btn value='귀숙10000'><input type=submit name=btn value='차숙10000'></td>
</tr>
<tr>
<td align=center>접속제한</td>
<td><input type=submit name=btn value='접속 허용'><input type=submit name=btn value='접속 제한'></td>
</tr>
<tr>
<td align=center>명령 설정</td>
<td><input type=submit name=btn value='하야입력'><input type=submit name=btn value='방랑해산'></td>
</tr>
<tr>
<td align=center>메세지 전달</td>
<td><input type=textarea size=60 maxlength=255 name=msg style=background-color:black;color:white;><input type=submit name=btn value='메세지 전달'></td>
</tr>
</table>
</form>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= backButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
echo "
<option value={$general['no']} $style>{$general['name']}</option>";
}
echo "
</select>
</td>
<td width=100 align=center>아이템 지급</td>
<td width=504>
<select name=weap size=1 style='color:white;background-color:black;font-size:13px'>";
for($i=0; $i < 27; $i++) {
echo "
<option value={$i}>{$i}</option>";
}
?>
</select>
<input type=submit name=btn value='무기지급'>
<input type=submit name=btn value='책지급'>
<input type=submit name=btn value='말지급'>
<input type=submit name=btn value='도구지급'>
</td>
</tr>
<tr>
<td width=100 align=center>블럭</td>
<td width=504>
<input type=submit name=btn value='블럭 해제'><input type=submit name=btn value='1단계 블럭'><input type=submit name=btn value='2단계 블럭'><input type=submit name=btn value='3단계 블럭'><input type=submit name=btn value='무한삭턴'><br>
1단계:발언권, 2단계:턴블럭
</td>
</tr>
<tr>
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>이벤트</td>
<td><input type=submit name=btn value='특기 부여'><input type=submit name=btn value='공헌치1000'><input type=submit name=btn value='경험치1000'></td>
</tr>
<tr>
<td align=center>이벤트2</td>
<td><input type=submit name=btn value='보숙10000'><input type=submit name=btn value='궁숙10000'><input type=submit name=btn value='기숙10000'><input type=submit name=btn value='귀숙10000'><input type=submit name=btn value='차숙10000'></td>
</tr>
<tr>
<td align=center>접속제한</td>
<td><input type=submit name=btn value='접속 허용'><input type=submit name=btn value='접속 제한'></td>
</tr>
<tr>
<td align=center>턴설정</td>
<td><input type=submit name=btn value='00턴'><input type=submit name=btn value='랜덤턴'></td>
</tr>
<tr>
<td align=center>NPC해제</td>
<td><input type=submit name=btn value='NPC해제'><input type=submit name=btn value='하야입력'><input type=submit name=btn value='방랑해산'><input type=submit name=btn value='NPC설정'></td>
</tr>
<tr>
<td align=center>메세지 전달</td>
<td><input type=textarea size=60 maxlength=255 name=msg style=background-color:black;color:white;><input type=submit name=btn value='메세지 전달'></td>
</tr>
</table>
</form>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
</table>
</body>
</html>
</html>
+223 -93
View File
@@ -1,224 +1,354 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$btn = Util::getPost('btn');
$item = Util::getPost('item', 'string');
$genlist = Util::getPost('genlist', 'array_int');
$msg = Util::getPost('msg', 'string');
$btn = Util::getReq('btn');
$weap = Util::getReq('weap', 'int');
$genlist = Util::getReq('genlist', 'array_int');
$msg = Util::getReq('msg', 'string');
extractMissingPostToGlobals();
//로그인 검사
$session = Session::requireLogin()->loginGame()->setReadOnly();
if ($session->userGrade < 5) {
if($session->userGrade < 5) {
header('location:_admin2.php');
}
$generalID = $session->generalID;
if (!$generalID) {
if(!$generalID){
header('location:_admin2.php');
die();
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$src = MessageTarget::buildQuick($session->generalID);
$genObjList = [];
$env = [];
if ($genlist) {
$genObjList = General::createGeneralObjListFromDB($genlist);
$env = $gameStor->cacheAll();
}
switch ($btn) {
switch($btn) {
case "전체 접속허용":
$db->update('general', [
'con' => 0
'con'=>0
], true);
break;
case "전체 접속제한":
$db->update('general', [
'con' => 1000
'con'=>1000
], true);
break;
case "블럭 해제":
$db->update('general', [
'block' => 0
'block'=>0
], '`no` IN %li', $genlist);
DB::db()->query('update general set block=0 where no IN %li', $genlist);
break;
case "1단계 블럭":
$date = TimeUtil::now();
$date = date('Y-m-d H:i:s');
$db->update('general', [
'block' => 1,
'killturn' => 24
'block'=>1,
'killturn'=>24
], '`no` IN %li', $genlist);
$uid = $db->queryFirstColumn('SELECT `owner` FROM general WHERE `no` IN %li', $genlist);
RootDB::db()->update('member', [
'block_num' => $db->sqleval('block_num+1'),
'block_date' => $date
RootDB::db()->update('member',[
'block_num'=>$db->sqleval('block_num+1'),
'block_date'=>$date
], 'id IN %li', $uid);
break;
case "2단계 블럭":
$date = TimeUtil::now();
$date = date('Y-m-d H:i:s');
$db->update('general', [
'gold' => 0,
'rice' => 0,
'block' => 2,
'killturn' => 24
'gold'=>0,
'rice'=>0,
'block'=>2,
'killturn'=>24
], '`no` IN %li', $genlist);
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->update('member', [
'block_num' => $db->sqleval('block_num+1'),
'block_date' => $date
RootDB::db()->update('member',[
'block_num'=>$db->sqleval('block_num+1'),
'block_date'=>$date
], 'id IN %li', $uid);
break;
case "3단계 블럭":
$date = TimeUtil::now();
$date = date('Y-m-d H:i:s');
$db->update('general', [
'gold' => 0,
'rice' => 0,
'block' => 3,
'killturn' => 24
'gold'=>0,
'rice'=>0,
'block'=>3,
'killturn'=>24
], '`no` IN %li', $genlist);
$uid = $db->queryFirstColumn('SELECT `owner` from general where no IN %li', $genlist);
RootDB::db()->update('member', [
'block_num' => $db->sqleval('block_num+1'),
'block_date' => $date
RootDB::db()->update('member',[
'block_num'=>$db->sqleval('block_num+1'),
'block_date'=>$date
], 'id IN %li', $uid);
break;
case "무한삭턴":
$db->update('general', [
'killturn' => 8000
'killturn'=>8000
], '`no` IN %li', $genlist);
break;
case "강제 사망":
$date = TimeUtil::now(true);
$date = date('Y-m-d H:i:s');
$db->update('general', [
'killturn' => 0,
'turntime' => $date,
'turn0'=>EncodeCommand(0, 0, 0, 0),
'killturn'=>0,
'turntime'=>$date,
], '`no` IN %li', $genlist);
$db->update('general_turn', [
'action' => '휴식',
'arg' => '{}',
'brief' => '휴식',
], 'general_id IN %li AND turn_idx = 0', $genlist);
break;
case "특기 부여":
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
$text = "특기 부여!";
foreach($db->query("SELECT `no`,leader,power,intel,dex0,dex10,dex20,dex30,dex40 FROM general WHERE `no` IN %li", $genlist) as $general){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($general['no']), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
$specialWar = SpecialityConst::pickSpecialWar($general);
$db->update('general', [
'specage2'=>$db->sqleval('age'),
'special2'=>$specialWar
], 'no=%i', $general['no']);
$specialWarName = SpecialityConst::WAR[$specialWar][0];
$josaUl = JosaUtil::pick($specialWarName, '을');
pushGeneralHistory($general, "<C>●</>{$year}{$month}월:특기 【<b><C>{$specialWarName}</></b>】{$josaUl} 습득");
pushGenLog($general, ["<C>●</>특기 【<b><L>{$specialWarName}</></b>】{$josaUl} 익혔습니다!"]);
}
break;
case "경험치1000":
$text = $btn . " 지급!";
foreach ($genlist as $generalID) {
$text = $btn." 지급!";
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'experience' => $db->sqleval('experience+1000')
$db->update('general',[
'experience'=>$db->sqleval('experience+1000')
], '`no` IN %li', $genlist);
break;
case "공헌치1000":
$text = $btn . " 지급!";
foreach ($genlist as $generalID) {
$text = $btn." 지급!";
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'dedication' => $db->sqleval('dedication+1000')
$db->update('general',[
'dedication'=>$db->sqleval('dedication+1000')
], '`no` IN %li', $genlist);
break;
case "보숙10000":
$text = "보병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'dex1' => $db->sqleval('dex1+10000')
$db->update('general',[
'dex0'=>$db->sqleval('dex0+10000')
], '`no` IN %li', $genlist);
break;
case "궁숙10000":
$text = "궁병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'dex2' => $db->sqleval('dex2+10000')
$db->update('general',[
'dex10'=>$db->sqleval('dex10+10000')
], '`no` IN %li', $genlist);
break;
case "기숙10000":
$src = MessageTarget::buildQuick($session->generalID);
$text = "기병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'dex3' => $db->sqleval('dex3+10000')
$db->update('general',[
'dex20'=>$db->sqleval('dex20+10000')
], '`no` IN %li', $genlist);
break;
case "귀숙10000":
$src = MessageTarget::buildQuick($session->generalID);
$text = "귀병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'dex4' => $db->sqleval('dex4+10000')
$db->update('general',[
'dex30'=>$db->sqleval('dex30+10000')
], '`no` IN %li', $genlist);
break;
case "차숙10000":
$src = MessageTarget::buildQuick($session->generalID);
$text = "차병숙련도+10000 지급!";
foreach ($genlist as $generalID) {
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
$db->update('general', [
'dex5' => $db->sqleval('dex5+10000')
$db->update('general',[
'dex40'=>$db->sqleval('dex40+10000')
], '`no` IN %li', $genlist);
break;
case "접속 허용":
$db->update('general', [
'con' => 0
$db->update('general',[
'con'=>0
], '`no` IN %li', $genlist);
break;
case "접속 제한":
$db->update('general', [
'con' => 1000
$db->update('general',[
'con'=>1000
], '`no` IN %li', $genlist);
break;
case "메세지 전달":
$text = $msg ?? '';
foreach ($genlist as $generalID) {
$text = $msg;
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
break;
case "무기지급":
if($weap == 0) {
$text = "무기 회수!";
}
else {
$text = getWeapName($weap)." 지급!";
}
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if($weap == 0){
$db->update('general', [
'weap'=>0
], '`no` IN %li', $genlist);
}
else{
$db->update('general', [
'weap'=>$weap
], '`no` IN %li AND weap < %i', $genlist, $weap);
}
break;
case "책지급":
if($weap == 0) {
$text = "책 회수!";
}
else {
$text = getBookName($weap)." 지급!";
}
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if($weap == 0){
$db->update('general', [
'book'=>0
], '`no` IN %li', $genlist);
}
else{
$db->update('general', [
'book'=>$weap
], '`no` IN %li AND book < %i', $genlist, $weap);
}
break;
case "말지급":
if($weap == 0) {
$text = "말 회수!";
}
else {
$text = getHorseName($weap)." 지급!";
}
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if($weap == 0){
$db->update('general', [
'horse'=>0
], '`no` IN %li', $genlist);
}
else{
$db->update('general', [
'horse'=>$weap
], '`no` IN %li AND horse < %i', $genlist, $weap);
}
break;
case "도구지급":
if($weap == 0) {
$text = "특수도구 회수!";
}
else {
$text = getItemName($weap)." 지급!";
}
foreach($genlist as $generalID){
$msg = new Message(Message::MSGTYPE_PRIVATE, $src, MessageTarget::buildQuick($generalID), $text, new \DateTime(), new \DateTime('9999-12-31'), []);
$msg->send(true);
}
if($weap == 0){
$db->update('general', [
'item'=>0
], '`no` IN %li', $genlist);
}
else{
$db->update('general', [
'item'=>$weap
], '`no` IN %li AND item < %i', $genlist, $weap);
}
break;
case "NPC해제":
$db->update('general', [
'npc'=>1
], '`no` IN %li', $genlist);
break;
case "하야입력":
$db->update('general_turn', [
'action' => 'che_하야',
'arg' => '{}',
'brief' => '하야',
], 'general_id IN %li AND turn_idx = 0', $genlist);
$db->update('general', [
'turn0'=>EncodeCommand(0, 0, 0, 45)
], '`no` IN %li', $genlist);
break;
case "방랑해산":
$db->update('general_turn', [
'action' => 'che_방랑',
'arg' => '{}',
'brief' => '방랑',
], 'general_id IN %li AND turn_idx = 0', $genlist);
$db->update('general_turn', [
'action' => 'che_해산',
'arg' => '{}',
'brief' => '해산',
], 'general_id IN %li AND turn_idx = 1', $genlist);
$db->update('general', [
'turn0'=>EncodeCommand(0, 0, 0, 47),
'turn1'=>EncodeCommand(0, 0, 0, 56)
], '`no` IN %li', $genlist);
break;
case "NPC설정":
$db->update('general', [
'npc'=>2
], '`no` IN %li', $genlist);
break;
case "00턴":
$turnterm = $gameStor->turnterm;
foreach($genlist as $generalID){
$turntime = getRandTurn($turnterm);
$cutTurn = cutTurn($turntime, $turnterm);
$db->update('general', [
'turntime'=>$curTurn
], '`no` IN %li', $genlist);
}
break;
case "랜덤턴":
foreach($genlist as $generalID){
$turntime = getRandTurn($turnterm);
$db->update('general', [
'turntime'=>$turntime
], '`no` IN %li', $genlist);
}
break;
}
header('location:_admin2.php');
header('location:_admin2.php');
+115 -105
View File
@@ -1,5 +1,4 @@
<?php
namespace sammo;
include "lib.php";
@@ -7,126 +6,137 @@ include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 5) {
die(requireAdminPermissionHTML());
if($session->userGrade < 5) {
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
관리자가 아닙니다.<br>
<?=banner()?>
</body>
</html>
<?php
exit();
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$connect=$db->get();
$conlimit = $gameStor->conlimit;
$ipGroupList = Util::arrayGroupBy(
$db->query(
'SELECT name,ip,lastconnect,owner,block,substring_index(ip,".",3) as ip_c from general WHERE ip!="" and npc<2'
),
'ip_c'
);
function colorBlockedName($general)
{
if (!$general['blocked']) {
return $general['name'];
}
return "<span style='color:magenta;'>{$general['name']}</span>";
}
?>
<!DOCTYPE html>
<html>
<head>
<title>멀티관리</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<title>멀티관리</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td> <br><?= backButton() ?></td>
</tr>
</table>
<form name=form1 method=post action=_admin4_submit.php>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center rowspan=3>회원선택<br><br>
<font color=cyan>NPC</font><br>
<font color=skyblue>NPC유저</font><br>
<font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b>
</td>
<td width=105 rowspan=3>
<?php
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=backButton()?></td></tr>
</table>
<form name=form1 method=post action=_admin4_submit.php>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=80 align=center rowspan=3>회원선택<br><br><font color=cyan>NPC</font><br><font color=skyblue>NPC유저</font><br><font color=red>접속제한</font><br><b style=background-color:red;>블럭회원</b></td>
<td width=105 rowspan=3>
<?php
echo "
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:14px'>";
echo "
<select name=genlist[] size=20 multiple style='color:white;background-color:black;font-size:13px'>";
foreach ($db->query('SELECT no,name,npc,block,con from general where ip!=\'\' order by npc,ip') as $general) {
$style = "style=;";
if ($general['block'] > 0) {
$style .= "background-color:red;";
}
foreach($db->query('SELECT no,name,npc,block,con from general where ip!=\'\' order by npc,ip') as $general){
$style = "style=;";
if($general['block'] > 0) { $style .= "background-color:red;"; }
if($general['npc'] >= 2) { $style .= "color:cyan;"; }
elseif($general['npc'] == 1) { $style .= "color:skyblue;"; }
if($general['con'] > $conlimit) { $style .= "color:red;"; }
$npcColor = getNPCColor($general['npc']);
if($npcColor !== null){
$style .= "color:{$npcColor};";
}
echo "
echo "
<option value={$general['no']} $style>{$general['name']}</option>";
}
}
echo "
echo "
</select>";
?>
</td>
<td width=100 align=center>블럭</td>
<td width=504>
<input type=submit name=btn value='블럭 해제'><input type=submit name=btn value='1단계 블럭'><input type=submit name=btn value='2단계 블럭'><input type=submit name=btn value='3단계 블럭'><input type=submit name=btn value='무한삭턴'><br>
1단계:발언권, 2단계:턴블럭
</td>
</tr>
<tr>
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>메세지 전달</td>
<td><input type=textarea size=60 maxlength=255 name=msg style=background-color:black;color:white;><input type=submit name=btn value='메세지 전달'></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td align=center width=100>장수명</td>
<td align=center width=180>최근로그인</td>
<td align=center width=129>IP</td>
<td align=center width=100>ID</td>
</tr>
<?php foreach ($ipGroupList as $ipGroupC => $users) : ?>
<tr>
<td><?= join('<br>', array_map('\sammo\colorBlockedName', $users)) ?></td>
<td><?= join('<br>', array_column($users, 'lastconnect')) ?></td>
<td><?= join('<br>', array_column($users, 'ip')) ?></td>
<td><?= join('<br>', array_column($users, 'owner')) ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php
//NOTE: password의 md5 해시가 같은지 확인하는 방식으로는 앞으로 잡아낼 수 없다. 폐기
?>
</form>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= backButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
</body>
?>
</td>
<td width=100 align=center>블럭</td>
<td width=504>
<input type=submit name=btn value='블럭 해제'><input type=submit name=btn value='1단계 블럭'><input type=submit name=btn value='2단계 블럭'><input type=submit name=btn value='3단계 블럭'><input type=submit name=btn value='무한삭턴'><br>
1단계:발언권, 2단계:턴블럭
</td>
</tr>
<tr>
<td align=center>강제 사망</td>
<td><input type=submit name=btn value='강제 사망'></td>
</tr>
<tr>
<td align=center>메세지 전달</td>
<td><input type=textarea size=60 maxlength=255 name=msg style=background-color:black;color:white;><input type=submit name=btn value='메세지 전달'></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td align=center width=100>장수명</td>
<td align=center width=180>최근로그인</td>
<td align=center width=129>IP</td>
<td align=center width=100>ID</td>
</tr>
<tr>
<?php
$query = "select substring_index(ip,'.',3) as ip2 from general where ip!='' and npc<2 group by ip2 having count(*)>1";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$ipCount = MYDB_num_rows($result);
$genName = "";
$genDate = "";
$genIP = "";
$genID = "";
for($i=0; $i < $ipCount; $i++) {
$ip = MYDB_fetch_array($result);
</html>
$query = "select name,ip,lastconnect,owner,block from general where ip like '{$ip['ip2']}%' and npc<2 order by ip";
$genResult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$genCount = MYDB_num_rows($genResult);
for($k=0; $k < $genCount; $k++) {
$gen = MYDB_fetch_array($genResult);
if($gen['block'] > 0) $genName .= "<font color=magenta>{$gen['name']}</font><br>";
else $genName .= $gen['name']."<br>";
$genDate .= $gen['lastconnect']."<br>";
$genIP .= $gen['ip']."<br>";
$genID .= $gen['owner']."<br>";
}
$genName .= "<br>";
$genDate .= "<br>";
$genIP .= "<br>";
$genID .= "<br>";
}
echo "
<td align=right>$genName</td>
<td>$genDate</td>
<td>$genIP</td>
<td>$genID</td>";
?>
</tr>
</table>
<?php
//NOTE: password의 md5 해시가 같은지 확인하는 방식으로는 앞으로 잡아낼 수 없다. 폐기
?>
</form>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
</table>
</body>
</html>
+23 -28
View File
@@ -1,5 +1,4 @@
<?php
namespace sammo;
include "lib.php";
@@ -7,74 +6,69 @@ include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 5) {
if($session->userGrade < 5) {
header('location:_admin4.php');
die();
}
$btn = Util::getPost('btn');
$genlist = Util::getPost('genlist', 'array_int');
$msg = Util::getPost('msg', 'string', '메시지');
$btn = Util::getReq('btn');
$genlist = Util::getReq('genlist', 'array_int');
$msg = Util::getReq('msg','string', '메시지');
extractMissingPostToGlobals();
$db = DB::db();
//NOTE: 왜 기능이 admin2와 admin4가 같이 있는가?
//NOTE: 왜 블럭 시 admin4에선 금쌀을 없애지 않는가?
switch ($btn) {
switch($btn) {
case "블럭 해제":
DB::db()->query('update general set block=0 where no IN %li', $genlist);
break;
case "1단계 블럭":
$date = TimeUtil::now();
$date = date('Y-m-d H:i:s');
$db = DB::db();
$db->query('update general set block=1,killturn=24 where no IN %li', $genlist);
$db->query('update general set block=1,killturn=24 where no IN %li',$genlist);
//FIXME: subquery로 하는게 더 빠를 듯.
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
break;
case "2단계 블럭":
$date = TimeUtil::now();
$date = date('Y-m-d H:i:s');
$db = DB::db();
$db->query('update general set block=2,killturn=24 where no IN %li', $genlist);
$db->query('update general set block=2,killturn=24 where no IN %li',$genlist);
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
break;
case "3단계 블럭":
$date = TimeUtil::now();
$date = date('Y-m-d H:i:s');
$db = DB::db();
$db->query('update general set block=3,killturn=24 where no IN %li', $genlist);
$db->query('update general set block=3,killturn=24 where no IN %li',$genlist);
$uid = $db->queryFirstColumn('select owner from general where no IN %li', $genlist);
RootDB::db()->query('update member set block_num=block_num+1,block_date=%s where id IN %ls', $date, $uid);
break;
case "무한삭턴":
DB::db()->query('update general set killturn=8000 where no IN %li', $genlist);
DB::db()->query('update general set killturn=8000 where no IN %li',$genlist);
break;
case "강제 사망":
$date = TimeUtil::now(true);
$db->update('general', [
'killturn' => 0,
'turntime' => $date,
], '`no` IN %li', $genlist);
$db->update('general_turn', [
'action' => '휴식',
'arg' => '{}',
'brief' => '휴식'
], 'general_id IN %li AND turn_idx = 0', $genlist);
$date = date('Y-m-d H:i:s');
DB::db()->query('update general set turn0=%s,killturn=0,turntime=%s where no IN %li',EncodeCommand(0, 0, 0, 0),$date, $genlist);
break;
case "메세지 전달":
$date = TimeUtil::now();
//TODO:새 갠메 시스템으로 변경
$date = date('Y-m-d H:i:s');
$src = MessageTarget::buildQuick($session->generalID);
foreach($genlist as $generalID){
for($i=0; $i < count($genlist); $i++) {
$msgObj = new Message(
Message::MSGTYPE_PRIVATE,
$src,
MessageTarget::buildQuick($generalID),
MessageTarget::buildQuick($genlist[$i]),
$msg,
new \DateTime(),
new DateTime(),
new \DateTime('9999-12-31'),
[]
);
if ($msgObj) {
if($msgObj){
$msgObj->send(true);
}
}
@@ -82,3 +76,4 @@ switch ($btn) {
}
header('location:_admin4.php');
+247 -289
View File
@@ -1,30 +1,47 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
/** @var int */
$type = Util::getPost('type', 'int', 0);
/** @var int */
$type2 = Util::getPost('type2', 'int', 0);
$type = Util::getReq('type', 'int', 0);
$type2 = Util::getReq('type2', 'int', 0);
if ($type < 0 || $type > 17) {
if($type < 0 || $type > 17){
$type = 0;
}
if ($type2 < 0 || $type2 > 6) {
if($type2 < 0 || $type2 > 6){
$type2 = 0;
}
extractMissingPostToGlobals();
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if ($session->userGrade < 5) {
die(requireAdminPermissionHTML());
if($session->userGrade < 5) {
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
관리자가 아닙니다.<br>
<?=banner()?>
</body>
</html>
<?php
exit();
}
$db = DB::db();
$connect=$db->get();
$sel = [];
$sel2 = [];
@@ -34,334 +51,275 @@ $sel2[$type2] = "selected";
?>
<!DOCTYPE html>
<html>
<head>
<title>일제정보</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printDist('ts', 'common', true) ?>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css" />
<title>일제정보</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td> <br><?= closeButton() ?></td>
</tr>
<tr>
<td>
<form name=form1 method=post>정렬순서 :
<select name=type size=1>
<option <?= $sel[0] ?? '' ?> value=0>국</option>
<option <?= $sel[1] ?? '' ?> value=1>장수</option>
<option <?= $sel[2] ?? '' ?> value=2>기술</option>
<option <?= $sel[3] ?? '' ?> value=3>국고</option>
<option <?= $sel[4] ?? '' ?> value=4>병량</option>
<option <?= $sel[5] ?? '' ?> value=5>평</option>
<option <?= $sel[6] ?? '' ?> value=6>평</option>
<option <?= $sel[7] ?? '' ?> value=7>평통</option>
<option <?= $sel[8] ?? '' ?> value=8>평무</option>
<option <?= $sel[9] ?? '' ?> value=9>평지</option>
<option <?= $sel[10] ?? '' ?> value=10>평Lv</option>
<option <?= $sel[11] ?? '' ?> value=11>접속률</option>
<option <?= $sel[12] ?? '' ?> value=12>단기접</option>
<option <?= $sel[13] ?? '' ?> value=13>보숙</option>
<option <?= $sel[14] ?? '' ?> value=14>궁숙</option>
<option <?= $sel[15] ?? '' ?> value=15>기숙</option>
<option <?= $sel[16] ?? '' ?> value=16>귀숙</option>
<option <?= $sel[17] ?? '' ?> value=17>차숙</option>
</select>
<select name=type2 size=1>
<option <?= $sel2[0] ?? '' ?> value=0>국력</option>
<option <?= $sel2[1] ?? '' ?> value=1>국가별성향</option>
<option <?= $sel2[2] ?? '' ?> value=2>국가성향</option>
<option <?= $sel2[3] ?? '' ?> value=3>장수성격</option>
<option <?= $sel2[4] ?? '' ?> value=4>장수특기</option>
<option <?= $sel2[5] ?? '' ?> value=5>병종수</option>
<option <?= $sel2[6] ?? '' ?> value=6>기타</option>
</select>
<input type=submit value='정렬하기'>
</form>
<form name=form2 method=post action=_admin5_submit.php>
<select name=nation size=1 style=color:white;background-color:black>";
<option value=0>재야</option>";
<?php
foreach ($db->query('SELECT nation,name,color,scout,gennum from nation order by power DESC') as $nation) {
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=closeButton()?></td></tr>
<tr><td>
<form name=form1 method=post>정렬순서 :
<select name=type size=1>
<option <?=$sel[0]??''?> value=0>국력</option>
<option <?=$sel[1]??''?> value=1>장수</option>
<option <?=$sel[2]??''?> value=2>기술</option>
<option <?=$sel[3]??''?> value=3>국</option>
<option <?=$sel[4]??''?> value=4>병량</option>
<option <?=$sel[5]??''?> value=5>평금</option>
<option <?=$sel[6]??''?> value=6>평쌀</option>
<option <?=$sel[7]??''?> value=7>평통</option>
<option <?=$sel[8]??''?> value=8>평</option>
<option <?=$sel[9]??''?> value=9>평</option>
<option <?=$sel[10]??''?> value=10>평Lv</option>
<option <?=$sel[11]??''?> value=11>접속률</option>
<option <?=$sel[12]??''?> value=12>단기접</option>
<option <?=$sel[13]??''?> value=13>보숙</option>
<option <?=$sel[14]??''?> value=14>궁숙</option>
<option <?=$sel[15]??''?> value=15>기숙</option>
<option <?=$sel[16]??''?> value=16>귀숙</option>
<option <?=$sel[17]??''?> value=17>차숙</option>
</select>
<select name=type2 size=1>
<option <?=$sel2[0]??''?> value=0>국력</option>
<option <?=$sel2[1]??''?> value=1>국가별성향</option>
<option <?=$sel2[2]??''?> value=2>국가성향</option>
<option <?=$sel2[3]??''?> value=3>장수성격</option>
<option <?=$sel2[4]??''?> value=4>장수특기</option>
<option <?=$sel2[5]??''?> value=5>병종수</option>
<option <?=$sel2[6]??''?> value=6>기타</option>
</select>
<input type=submit value='정렬하기'>
</form>
<form name=form2 method=post action=_admin5_submit.php>
<select name=nation size=1 style=color:white;background-color:black>";
<option value=0>재야</option>";
<?php
$query = "select nation,name,color,scout,scoutmsg,gennum from nation order by power";
$result = MYDB_query($query, $connect) or Error("aaa_processing.php ".MYDB_error($connect),"");
$count = MYDB_num_rows($result);
for($i=1; $i <= $count; $i++) {
$nation = MYDB_fetch_array($result);
echo "
echo "
<option value={$nation['nation']}>{$nation['name']}</option>";
}
?>
</select>
<input type=submit name=btn value='국가변경'>
</form>
</td>
</tr>
</table>
}
?>
</select>
<input type=submit name=btn value='국가변경'>
</form>
</td></tr>
</table>
<table align=center width=1600 class="tb_layout bg0">
<tr class='bg1'>
<td align=center>국명</td>
<td align=center>접률</td>
<td align=center>단접</td>
<td align=center>국력</td>
<td align=center>장수</td>
<td align=center>속령</td>
<td align=center>기술</td>
<td align=center>전략</td>
<td align=center>국고</td>
<td align=center>병량</td>
<td align=center>평금</td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center>Lv</td>
<td align=center>보숙</td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center>총병</td>
<td align=center>인구</td>
<td align=center>인구</td>
<td align=center>농업</td>
<td align=center></td>
<td align=center>치안</td>
<td align=center>성벽</td>
<td align=center>수비</td>
<td align=center>국명</td>
</tr>
<?php
$query = "
<table align=center width=1600 class="tb_layout bg0">
<tr id=bg1>
<td align=center>국명</td>
<td align=center>접률</td>
<td align=center>단접</td>
<td align=center>국력</td>
<td align=center>단합</td>
<td align=center>장수</td>
<td align=center>속령</td>
<td align=center>기술</td>
<td align=center>전략</td>
<td align=center>국고</td>
<td align=center>병량</td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center>평Lv</td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center></td>
<td align=center>차숙</td>
<td align=center>총병</td>
<td align=center>인구</td>
<td align=center>인구율</td>
<td align=center></td>
<td align=center>상업</td>
<td align=center>치안</td>
<td align=center>성벽</td>
<td align=center>수비</td>
<td align=center>국명</td>
</tr>
<?php
$query = "
SELECT
A.nation,
A.name,
A.power,
A.chemi,
A.color,
A.tech,
A.strategic_cmd_limit,
A.sabotagelimit,
A.gold,
A.rice,
COUNT(B.nation) AS gennum,
ROUND(AVG(B.connect), 1) AS connect,
ROUND(AVG(B.con), 1) AS con,
ROUND(AVG(B.dex1)) AS dex1,
ROUND(AVG(B.dex2)) AS dex2,
ROUND(AVG(B.dex3)) AS dex3,
ROUND(AVG(B.dex4)) AS dex4,
ROUND(AVG(B.dex5)) AS dex5
ROUND(AVG(B.dex0)) AS dex0,
ROUND(AVG(B.dex10)) AS dex10,
ROUND(AVG(B.dex20)) AS dex20,
ROUND(AVG(B.dex30)) AS dex30,
ROUND(AVG(B.dex40)) AS dex40
FROM nation A, general B
WHERE A.nation=B.nation
GROUP BY B.nation
";
switch ($type) {
case 0:
$query .= " order by power desc";
break;
case 1:
$query .= " order by gennum desc";
break;
case 2:
$query .= " order by A.tech desc";
break;
case 3:
$query .= " order by A.gold desc";
break;
case 4:
$query .= " order by A.rice desc";
break;
case 5:
$query .= " order by avg(B.gold) desc";
break;
case 6:
$query .= " order by avg(B.rice) desc";
break;
case 7:
$query .= " order by avg(B.leadership) desc";
break;
case 8:
$query .= " order by avg(B.strength) desc";
break;
case 9:
$query .= " order by avg(B.intel) desc";
break;
case 10:
$query .= " order by avg(B.explevel) desc";
break;
case 11:
$query .= " order by avg(B.connect) desc";
break;
case 12:
$query .= " order by avg(B.con) desc";
break;
case 13:
$query .= " order by avg(B.dex1) desc";
break;
case 14:
$query .= " order by avg(B.dex2) desc";
break;
case 15:
$query .= " order by avg(B.dex3) desc";
break;
case 16:
$query .= " order by avg(B.dex4) desc";
break;
case 17:
$query .= " order by avg(B.dex5) desc";
break;
}
foreach ($db->query($query) as $nation) {
$gen = $db->queryFirstRow('SELECT COUNT(*) as cnt,
ROUND(AVG(gold)) as avgg,
ROUND(AVG(rice)) as avgr,
SUM(leadership) as leadership, ROUND(AVG(leadership), 1) as avgl,
ROUND(AVG(strength), 1) as avgs,
ROUND(AVG(intel), 1) as avgi,
ROUND(AVG(explevel), 1) as avge,
SUM(crew) as crew
from general where nation=%i', $nation['nation']);
switch($type) {
case 0: $query .= " order by power desc"; break;
case 1: $query .= " order by gennum desc"; break;
case 2: $query .= " order by A.tech desc"; break;
case 3: $query .= " order by A.gold desc"; break;
case 4: $query .= " order by A.rice desc"; break;
case 5: $query .= " order by avg(B.gold) desc"; break;
case 6: $query .= " order by avg(B.rice) desc"; break;
case 7: $query .= " order by avg(B.leader) desc"; break;
case 8: $query .= " order by avg(B.power) desc"; break;
case 9: $query .= " order by avg(B.intel) desc"; break;
case 10: $query .= " order by avg(B.explevel) desc"; break;
case 11: $query .= " order by avg(B.connect) desc"; break;
case 12: $query .= " order by avg(B.con) desc"; break;
case 13: $query .= " order by avg(B.dex0) desc"; break;
case 14: $query .= " order by avg(B.dex10) desc"; break;
case 15: $query .= " order by avg(B.dex20) desc"; break;
case 16: $query .= " order by avg(B.dex30) desc"; break;
case 17: $query .= " order by avg(B.dex40) desc"; break;
}
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$nationCount = MYDB_num_rows($result);
for($i=0; $i < $nationCount; $i++) {
$nation = MYDB_fetch_array($result);
$city = $db->queryFirstRow('SELECT COUNT(*) as cnt,
SUM(pop) as pop, SUM(pop_max) as pop_max,
ROUND(SUM(pop)/SUM(pop_max)*100, 2) as rate,
trust,
ROUND(SUM(agri)/SUM(agri_max)*100, 2) as agri,
ROUND(SUM(comm)/SUM(comm_max)*100, 2) as comm,
ROUND(SUM(secu)/SUM(secu_max)*100, 2) as secu,
ROUND(SUM(wall)/SUM(wall_max)*100, 2) as wall,
ROUND(SUM(def)/SUM(def_max)*100, 2) as def
from city where nation=%i', $nation['nation']);
$query = "select COUNT(*) as cnt,
ROUND(AVG(gold)) as avgg,
ROUND(AVG(rice)) as avgr,
SUM(leader) as leader, ROUND(AVG(leader), 1) as avgl,
ROUND(AVG(power), 1) as avgp,
ROUND(AVG(intel), 1) as avgi,
ROUND(AVG(explevel), 1) as avge,
SUM(crew) as crew
from general where nation='{$nation['nation']}'";
$genResult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gen = MYDB_fetch_array($genResult);
echo "
$query = "select COUNT(*) as cnt,
SUM(pop) as pop, SUM(pop2) as pop2,
ROUND(SUM(pop)/SUM(pop2)*100, 2) as rate,
ROUND(SUM(agri)/SUM(agri2)*100, 2) as agri,
ROUND(SUM(comm)/SUM(comm2)*100, 2) as comm,
ROUND(SUM(secu)/SUM(secu2)*100, 2) as secu,
ROUND(SUM(wall)/SUM(wall2)*100, 2) as wall,
ROUND(SUM(def)/SUM(def2)*100, 2) as def
from city where nation='{$nation['nation']}'";
$cityResult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$city = MYDB_fetch_array($cityResult);
echo "
<tr>
<td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td>
<td align=center style=background-color:{$nation['color']};color:".newColor($nation['color']).";>{$nation['name']}</td>
<td align=center>&nbsp;{$nation['connect']}&nbsp;</td>
<td align=center>&nbsp;{$nation['con']}&nbsp;</td>
<td align=center>&nbsp;{$nation['power']}&nbsp;</td>
<td align=center>&nbsp;{$nation['chemi']}&nbsp;</td>
<td align=center>&nbsp;{$gen['cnt']}&nbsp;</td>
<td align=center>&nbsp;{$city['cnt']}&nbsp;</td>
<td align=right>&nbsp;" . sprintf('%.1f', $nation['tech']) . "&nbsp;</td>
<td align=center>&nbsp;{$nation['strategic_cmd_limit']}&nbsp;</td>
<td align=center>&nbsp;{$nation['tech']}&nbsp;</td>
<td align=center>&nbsp;{$nation['sabotagelimit']}&nbsp;</td>
<td align=center>&nbsp;{$nation['gold']}&nbsp;</td>
<td align=center>&nbsp;{$nation['rice']}&nbsp;</td>
<td align=right>&nbsp;{$gen['avgg']}&nbsp;</td>
<td align=right>&nbsp;{$gen['avgr']}&nbsp;</td>
<td align=right>&nbsp;{$gen['avgl']}&nbsp;</td>
<td align=right>&nbsp;{$gen['avgs']}&nbsp;</td>
<td align=right>&nbsp;{$gen['avgi']}&nbsp;</td>
<td align=right>&nbsp;{$gen['avge']}&nbsp;</td>
<td align=right>&nbsp;{$nation['dex1']}&nbsp;</td>
<td align=right>&nbsp;{$nation['dex2']}&nbsp;</td>
<td align=right>&nbsp;{$nation['dex3']}&nbsp;</td>
<td align=right>&nbsp;{$nation['dex4']}&nbsp;</td>
<td align=right>&nbsp;{$nation['dex5']}&nbsp;</td>
<td align=right>&nbsp;{$gen['crew']}/{$gen['leadership']}00&nbsp;</td>
<td align=center>&nbsp;{$city['pop']}/{$city['pop_max']}&nbsp;</td>
<td align=center>&nbsp;" . sprintf('%.1f', $city['pop'] / Util::valueFit($city['pop_max'], 1) * 100) . "%&nbsp;</td>
<td align=center>&nbsp;{$gen['avgg']}&nbsp;</td>
<td align=center>&nbsp;{$gen['avgr']}&nbsp;</td>
<td align=center>&nbsp;{$gen['avgl']}&nbsp;</td>
<td align=center>&nbsp;{$gen['avgp']}&nbsp;</td>
<td align=center>&nbsp;{$gen['avgi']}&nbsp;</td>
<td align=center>&nbsp;{$gen['avge']}&nbsp;</td>
<td align=center>&nbsp;{$nation['dex0']}&nbsp;</td>
<td align=center>&nbsp;{$nation['dex10']}&nbsp;</td>
<td align=center>&nbsp;{$nation['dex20']}&nbsp;</td>
<td align=center>&nbsp;{$nation['dex30']}&nbsp;</td>
<td align=center>&nbsp;{$nation['dex40']}&nbsp;</td>
<td align=center>&nbsp;{$gen['crew']}/{$gen['leader']}00&nbsp;</td>
<td align=center>&nbsp;{$city['pop']}/{$city['pop2']}&nbsp;</td>
<td align=center>&nbsp;{$city['rate']}%&nbsp;</td>
<td align=center>&nbsp;{$city['agri']}%&nbsp;</td>
<td align=center>&nbsp;{$city['comm']}%&nbsp;</td>
<td align=center>&nbsp;{$city['secu']}%&nbsp;</td>
<td align=center>&nbsp;{$city['wall']}%&nbsp;</td>
<td align=center>&nbsp;{$city['def']}%&nbsp;</td>
<td align=center style=background-color:{$nation['color']};color:" . newColor($nation['color']) . ";>{$nation['name']}</td>
<td align=center style=background-color:{$nation['color']};color:".newColor($nation['color']).";>{$nation['name']}</td>
</tr>
";
}
}
?>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= getSabotageLogRecent(20) ?></td>
</tr>
</table>
?>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=getSabotageLogRecent(20)?></td></tr>
</table>
<table align=center width=1760 class="tb_layout bg0">
<tr class='bg1'>
<td width=30 align=center></td>
<td width=30 align=center></td>
<td width=50 align=center>국가수</td>
<td width=50 align=center>장수수</td>
<?php
switch ($type2) {
default:
case 0:
echo "<td width=1600>국력(국력,장수수,도시수,인구/100,최대인구/100,국가자원/100,장수자원/100,능력치,숙련/1000,경험공헌/100)</td>";
break;
case 1:
echo "<td width=1600>국가별성향</td>";
break;
case 2:
echo "<td width=1600>국가성향</td>";
break;
case 3:
echo "<td width=1600>장수성격</td>";
break;
case 4:
echo "<td width=1600>장수특기</td>";
break;
case 5:
echo "<td width=1600>병종수</td>";
break;
case 6:
echo "<td width=1600>기타</td>";
break;
}
?>
</tr>
<?php
foreach ($db->query('SELECT * from statistic where month=1 or no=1') as $stat) {
echo "
<table align=center width=1760 class="tb_layout bg0">
<tr id=bg1>
<td width=30 align=center></td>
<td width=30 align=center></td>
<td width=50 align=center>국가수</td>
<td width=50 align=center>장수수</td>
<?php
switch($type2) {
default:
case 0: echo "<td width=1600>국력(국력,장수수,도시수,인구/100,최대인구/100,국가자원/100,장수자원/100,능력치,숙련/1000,경험공헌/100)</td>"; break;
case 1: echo "<td width=1600>국가별성향</td>"; break;
case 2: echo "<td width=1600>국가성향</td>"; break;
case 3: echo "<td width=1600>장수성격</td>"; break;
case 4: echo "<td width=1600>장수특기</td>"; break;
case 5: echo "<td width=1600>병종수</td>"; break;
case 6: echo "<td width=1600>기타</td>"; break;
}
?>
</tr>
<?php
$query = "select * from statistic where month=1 or no=1";
$result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$count = MYDB_num_rows($result);
for($i=0; $i < $count; $i++) {
$stat = MYDB_fetch_array($result);
echo "
<tr>
<td align=center>{$stat['year']}</td>
<td align=center>{$stat['month']}</td>
<td align=center>{$stat['nation_count']}</td>
<td align=center>{$stat['gen_count']}</td>
";
switch ($type2) {
default:
case 0:
echo "<td>{$stat['power_hist']}</td>";
break;
case 1:
echo "<td>{$stat['nation_name']}</td>";
break;
case 2:
echo "<td>{$stat['nation_hist']}</td>";
break;
case 3:
echo "<td>{$stat['personal_hist']}</td>";
break;
case 4:
echo "<td>{$stat['special_hist']}</td>";
break;
case 5:
echo "<td>{$stat['crewtype']}</td>";
break;
case 6:
echo "<td>{$stat['etc']}</td>";
break;
}
echo "
switch($type2) {
default:
case 0: echo "<td>{$stat['power_hist']}</td>"; break;
case 1: echo "<td>{$stat['nation_name']}</td>"; break;
case 2: echo "<td>{$stat['nation_hist']}</td>"; break;
case 3: echo "<td>{$stat['personal_hist']}</td>"; break;
case 4: echo "<td>{$stat['special_hist']}</td>"; break;
case 5: echo "<td>{$stat['crewtype']}</td>"; break;
case 6: echo "<td>{$stat['etc']}</td>"; break;
}
echo "
</tr>
";
}
?>
</table>
}
?>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td><?= closeButton() ?></td>
</tr>
<tr>
<td><?= banner() ?> </td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
</table>
</body>
</html>
</html>
+14 -21
View File
@@ -1,49 +1,42 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$btn = Util::getPost('btn');
$nation = Util::getPost('nation', 'int');
$btn = Util::getReq('btn');
$nation = Util::getReq('nation', 'int');
extractMissingPostToGlobals();
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
if ($session->userGrade < 5) {
if($session->userGrade < 5) {
header('location:_admin5.php');
die();
}
$db = DB::db();
$connect=$db->get();
switch ($btn) {
switch($btn) {
case "국가변경":
$oldNation = $db->queryFirstField('SELECT nation FROM general WHERE owner=%i', $userID);
if ($nation == 0) {
if($nation == 0) {
$db->update('general', [
'nation' => 0,
'officer_level' => 0,
'officer_city' => 0
'nation'=>0,
'level'=>0,
], 'owner=%i', $userID);
} else {
$db->update('general', [
'nation' => $nation,
'officer_level' => 1,
'officer_city' => 0
'nation'=>$nation,
'level'=>1,
], 'owner=%i', $userID);
$db->update('nation', [
'gennum' => $db->sqleval('gennum + 1')
], 'nation=%i', $oldNation);
}
if ($oldNation != 0) {
$db->update('nation', [
'gennum' => $db->sqleval('gennum - 1')
], 'nation=%i', $oldNation);
}
break;
}
header('location:_admin5.php');
+111
View File
@@ -0,0 +1,111 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$type = Util::getReq('type', 'int', 0);
if($type < 0 || $type > 4){
$type = 0;
}
extractMissingPostToGlobals();
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
if($session->userGrade < 5) {
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
관리자가 아닙니다.<br>
<?=banner()?>
</body>
</html>
<?php
exit();
}
$db = DB::db();
$connect=$db->get();
$sel[$type] = "selected";
?>
<!DOCTYPE html>
<html>
<head>
<title>접속정보</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=closeButton()?></td></tr>
<tr><td><form name=form1 method=post>정렬순서 :
<select name=type size=1>
<option <?=$sel[0]??''?> value=0>접속률</option>
<option <?=$sel[1]??''?> value=1>총갱신</option>
<option <?=$sel[2]??''?> value=2>갱신/턴</option>
<option <?=$sel[3]??''?> value=3>총로그인</option>
<option <?=$sel[4]??''?> value=4>갱신/로그인</option>
</select>
<input type=submit value='정렬하기'></form>
</td></tr>
</table>
<table align=center class='tb_layout bg0'>
<tr id=bg1>
<td align=center width=120>장수명</td>
<td align=center width=50>접속률</td>
<td align=center width=40>시작연령</td>
<td align=center width=40>연령</td>
<td align=center width=80>총갱신</td>
<td align=center width=80>갱신/</td>
<td align=center width=80>총로그인</td>
<td align=center width=100>갱신/로그인</td>
</tr>
<?php
switch($type) {
case 0: $query = "select name,connect,startage,age,refcnt,logcnt,refcnt/(age-startage+1)/12 as ref,refcnt/logcnt as log from general order by connect desc limit 0,30"; break;
case 1: $query = "select name,connect,startage,age,refcnt,logcnt,refcnt/(age-startage+1)/12 as ref,refcnt/logcnt as log from general order by refcnt desc limit 0,30"; break;
case 2: $query = "select name,connect,startage,age,refcnt,logcnt,refcnt/(age-startage+1)/12 as ref,refcnt/logcnt as log from general order by ref desc limit 0,30"; break;
case 3: $query = "select name,connect,startage,age,refcnt,logcnt,refcnt/(age-startage+1)/12 as ref,refcnt/logcnt as log from general order by logcnt desc limit 0,30"; break;
case 4: $query = "select name,connect,startage,age,refcnt,logcnt,refcnt/(age-startage+1)/12 as ref,refcnt/logcnt as log from general order by log desc limit 0,30"; break;
}
$genresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
$gencount = MYDB_num_rows($genresult);
for($i=0; $i < $gencount; $i++) {
$gen = MYDB_fetch_array($genresult);
echo "
<tr>
<td align=center>{$gen['name']}</td>
<td align=center>{$gen['connect']}</td>
<td align=center>{$gen['startage']}</td>
<td align=center>{$gen['age']}</td>
<td align=center>".round($gen['refcnt']/2, 1)."</td>
<td align=center>".round($gen['ref']/2,1)."</td>
<td align=center>{$gen['logcnt']}</td>
<td align=center>".round($gen['log']/2,1)."</td>
</tr>";
}
?>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
</table>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More