forked from devsam/core
로그인 form draw 예시
This commit is contained in:
+131
-130
@@ -1,131 +1,132 @@
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
#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 .container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-group-xs>.btn,
|
||||
.btn-xs {
|
||||
padding: .25rem .4rem;
|
||||
font-size: .875rem;
|
||||
line-height: .5;
|
||||
border-radius: .2rem;
|
||||
}
|
||||
|
||||
#running_map {
|
||||
margin-top: 20px;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ $defaultPost = [
|
||||
'showMe' => false,
|
||||
];
|
||||
|
||||
$history = getGlobalHistoryLogRecent(15);
|
||||
$history = formatHistoryToHTML(getGlobalHistoryLogRecent(10));
|
||||
$rawMap = getWorldMap([
|
||||
'year' => null,
|
||||
'month' => null,
|
||||
@@ -63,7 +63,12 @@ $rawMap = getWorldMap([
|
||||
'showMe' => false,
|
||||
]);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$mapTheme = $gameStor->map_theme ?? 'che';
|
||||
|
||||
$rawMap['history'] = $history;
|
||||
$rawMap['theme'] = $mapTheme;
|
||||
|
||||
$etag = hash('sha256', $serverID.$now);
|
||||
$map = [
|
||||
|
||||
+685
-653
@@ -1,654 +1,686 @@
|
||||
|
||||
function is_touch_device() {
|
||||
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
var mq = function(query) {
|
||||
return window.matchMedia(query).matches;
|
||||
}
|
||||
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
function reloadWorldMap(option){
|
||||
var $world_map = $('.world_map');
|
||||
|
||||
if($world_map.length == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultOption = {
|
||||
isDetailMap:true, //복잡 지도, 단순 지도
|
||||
clickableAll:false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
|
||||
selectCallback:null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
|
||||
hrefTemplate:'#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
|
||||
useCachedMap:false, //맵 캐시를 사용
|
||||
|
||||
//아래부터는 post query에 들어갈 녀석
|
||||
year:null, //year값, 연감등에 사용
|
||||
month:null, //month값, 연감등에 사용
|
||||
aux:null, //기타 넣고 싶은 값을 입력
|
||||
neutralView:false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
|
||||
showMe:true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
|
||||
targetJson:'j_map.php',
|
||||
|
||||
//기타 보조 값
|
||||
startYear:null,
|
||||
};
|
||||
|
||||
option = $.extend(defaultOption, option);
|
||||
|
||||
var useCachedMap = option.useCachedMap;
|
||||
var isDetailMap = option.isDetailMap;
|
||||
var clickableAll = option.clickableAll;
|
||||
var selectCallback = option.selectCallback;
|
||||
var hrefTemplate = option.hrefTemplate;
|
||||
|
||||
var cityPosition = getCityPosition();
|
||||
|
||||
var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
|
||||
var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
|
||||
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
|
||||
|
||||
function checkReturnObject(obj){
|
||||
if(!obj.result){
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if(!$.isNumeric(obj.startYear)
|
||||
||!$.isNumeric(obj.year)
|
||||
||!$.isNumeric(obj.month)
|
||||
){
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if(useCachedMap){
|
||||
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
|
||||
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
|
||||
}
|
||||
|
||||
$world_map.removeClass('draw_required');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setMapBackground(obj){
|
||||
var startYear = obj.startYear;
|
||||
var year = obj.year;
|
||||
var month = obj.month;
|
||||
|
||||
if(isDetailMap){
|
||||
$world_map.addClass('map_detail').removeClass('map_basic');
|
||||
}
|
||||
else{
|
||||
$world_map.addClass('map_basic').removeClass('map_detail');
|
||||
}
|
||||
|
||||
var $map_title = $('.map_title_text');
|
||||
if(year < startYear + 1){
|
||||
$map_title.css('color', 'magenta');
|
||||
}
|
||||
else if(year < startYear + 2){
|
||||
$map_title.css('color', 'orange');
|
||||
}
|
||||
else if(year < startYear + 3){
|
||||
$map_title.css('color', 'yellow');
|
||||
}
|
||||
|
||||
$map_title_tooltip = $('.map_title .tooltiptext');
|
||||
$map_title_tooltip.empty();
|
||||
|
||||
var tooltipTexts = [];
|
||||
if(year < startYear + 3){
|
||||
var startYearText = [];
|
||||
var remainYear = startYear + 3 - year;
|
||||
var remainMonth = 12 - month + 1;
|
||||
if(remainMonth > 0){
|
||||
remainYear -= 1;
|
||||
}
|
||||
if(remainYear){
|
||||
startYearText.push('{0}년'.format(remainYear));
|
||||
}
|
||||
if(remainMonth){
|
||||
startYearText.push('{0}개월'.format(remainMonth));
|
||||
}
|
||||
|
||||
tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3));
|
||||
}
|
||||
|
||||
var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1;
|
||||
var nextTechLimitYear = currentTechLimit * 5 + startYear;
|
||||
|
||||
tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit+1));
|
||||
$map_title_tooltip.html(tooltipTexts.join('<br>'));
|
||||
|
||||
$world_map.removeClass('map_string map_summer map_fall map_winter');
|
||||
if(month <= 3){
|
||||
$world_map.addClass('map_spring');
|
||||
}
|
||||
else if(month <= 6){
|
||||
$world_map.addClass('map_summer');
|
||||
}
|
||||
else if(month <= 9){
|
||||
$world_map.addClass('map_fall');
|
||||
}
|
||||
else{
|
||||
$world_map.addClass('map_winter');
|
||||
}
|
||||
|
||||
$map_title.html('{0}年 {1}月'.format(year, month));
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function convertCityObjs(obj){
|
||||
//원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다.
|
||||
|
||||
function toCityObj(arr){
|
||||
return {
|
||||
id:arr[0],
|
||||
level:arr[1],
|
||||
state:arr[2],
|
||||
nationId:(arr[3]>0)?arr[3]:null,
|
||||
region:arr[4],
|
||||
supply:(arr[5]!=0)
|
||||
};
|
||||
}
|
||||
|
||||
function toNationObj(arr){
|
||||
return {
|
||||
id:arr[0],
|
||||
name:arr[1],
|
||||
color:arr[2],
|
||||
capital:arr[3]
|
||||
};
|
||||
}
|
||||
|
||||
var cityList = obj.cityList.map(toCityObj);
|
||||
var nationList = obj.nationList.map(toNationObj);
|
||||
nationList = convertDictById(nationList); //array of object -> dict
|
||||
|
||||
var spyList = obj.spyList;
|
||||
var shownByGeneralList = convertSet(obj.shownByGeneralList);//Array -> Set
|
||||
|
||||
var myCity = obj.myCity;
|
||||
var myNation = obj.myNation;
|
||||
|
||||
|
||||
function mergePositionInfo(city){
|
||||
var id = city.id;
|
||||
if(!(id in cityPosition)){
|
||||
return city;
|
||||
}
|
||||
var xy_val = cityPosition[id];
|
||||
city.name = xy_val[0];
|
||||
city.x = xy_val[1];
|
||||
city.y = xy_val[2];
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeNationInfo(city){
|
||||
//nationId 값으로 isCapital, color, nation을 통합
|
||||
|
||||
var nationId = city.nationId;
|
||||
if(nationId === null || !(nationId in nationList)){
|
||||
city.nationId = null;
|
||||
city.nation = null;
|
||||
city.color = null;
|
||||
city.isCapital = false;
|
||||
return city;
|
||||
}
|
||||
|
||||
var nationObj = nationList[nationId];
|
||||
city.nation = nationObj.name;
|
||||
city.color = nationObj.color;
|
||||
city.isCapital = (nationObj.capital == city.id);
|
||||
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeClickable(city){
|
||||
//clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
|
||||
var id = city.id;
|
||||
var nationId = city.nationId;
|
||||
var clickable = 0;
|
||||
if(id in spyList){
|
||||
clickable |= spyList[id] << 3;
|
||||
}
|
||||
if(myNation !== null && nationId == myNation){
|
||||
clickable |= 4;
|
||||
}
|
||||
if(shownByGeneralList.hasOwnProperty(id)){
|
||||
clickable |= 2;
|
||||
}
|
||||
if(myCity !== null && id == myCity){
|
||||
clickable |= 2;
|
||||
}
|
||||
if(clickableAll){
|
||||
clickable |= 1;
|
||||
}
|
||||
|
||||
|
||||
city.clickable = clickable;
|
||||
return city;
|
||||
}
|
||||
|
||||
cityList = cityList
|
||||
.map(mergePositionInfo)
|
||||
.map(mergeNationInfo)
|
||||
.map(mergeClickable)
|
||||
.map(formatCityInfo);
|
||||
|
||||
return {
|
||||
'cityList' : cityList,
|
||||
'myCity' : myCity
|
||||
};
|
||||
}
|
||||
|
||||
function drawDetailWorldMap(obj){
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city){
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15});
|
||||
|
||||
if('color' in city && city.color !== null){
|
||||
var $bgObj = $('<div class="city_bg"></div>');
|
||||
$cityObj.append($bgObj);
|
||||
$bgObj.css({'background-image':'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color))});
|
||||
}
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id});
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level));
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
|
||||
|
||||
if(city.state > 0){
|
||||
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
|
||||
$linkObj.append($stateObj);
|
||||
}
|
||||
|
||||
if(city.nationId && city.nationId > 0){
|
||||
var flagType = city.supply?'f':'d';
|
||||
var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
|
||||
if(city.isCapital){
|
||||
var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage));
|
||||
$flagObj.append($capitalObj);
|
||||
}
|
||||
$imgObj.append($flagObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
|
||||
$map_body.append($cityObj);
|
||||
|
||||
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function drawBasicWorldMap(obj){
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city){
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15});
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id});
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
|
||||
if('color' in city && city.color !== null){
|
||||
$imgObj.css({'background-color':city.color});
|
||||
}
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
if(city.state > 0){
|
||||
var state_text = 'wrong';
|
||||
if(city.state < 10){
|
||||
state_text = 'good';
|
||||
}
|
||||
else if(city.state < 40){
|
||||
state_text = 'bad';
|
||||
}
|
||||
else if(city.state < 50){
|
||||
state_text = 'war';
|
||||
}
|
||||
|
||||
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text));
|
||||
$imgObj.append($stateObj);
|
||||
}
|
||||
|
||||
//단순 표기에서는 깃발 여부가 없음
|
||||
if(city.isCapital){
|
||||
var $capitalObj = $('<div class="city_capital"></div>');
|
||||
$imgObj.append($capitalObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
$map_body.append($cityObj);
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setMouseWork(obj){
|
||||
var $tooltip = $('.world_map .city_tooltip');
|
||||
var $tooltip_city = $tooltip.find('.city_name');
|
||||
var $tooltip_nation = $tooltip.find('.nation_name');
|
||||
|
||||
var $objs = $('.world_map .city_link');
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
//터치스크린 탭
|
||||
|
||||
if(!option.neutralView && is_touch_device()){
|
||||
$objs.on('touchstart', function(e){
|
||||
if(window.sam_toggleSingleTap){
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if($tooltip_city.data('target') != $this.data('id')){
|
||||
$this.data('touchMode', 1);
|
||||
}
|
||||
else if(touchMode === undefined){
|
||||
$this.data('touchMode', 1);
|
||||
}
|
||||
else{
|
||||
$this.data('touchMode', touchMode + 1);
|
||||
}
|
||||
$map_body.data('touchMode', 1);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
|
||||
|
||||
});
|
||||
|
||||
$objs.on('touchend', function(e){
|
||||
if(window.sam_toggleSingleTap){
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
var position = $this.parent().position();
|
||||
$tooltip_city.html($this.data('text'));
|
||||
|
||||
var nation_text = $this.data('nation');
|
||||
if(nation_text){
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
}
|
||||
else{
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
$tooltip.css({'top': position.top + 25, 'left': position.left + 35}).show();
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if(touchMode <= 1){
|
||||
return false;
|
||||
}
|
||||
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
$this.data('touchMode', 0);
|
||||
});
|
||||
|
||||
$map_body.on('touchend',function(e){
|
||||
if(window.sam_toggleSingleTap){
|
||||
return true;
|
||||
}
|
||||
//위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Mouse over 모드 작동
|
||||
|
||||
$map_body.on('mousemove', function(e){
|
||||
if($(this).data('touchMode')){
|
||||
return true;
|
||||
}
|
||||
|
||||
var parentOffset = $map_body.offset();
|
||||
var relX = e.pageX - parentOffset.left;
|
||||
var relY = e.pageY - parentOffset.top;
|
||||
|
||||
$tooltip.css({'top': relY + 10, 'left': relX + 10});
|
||||
});
|
||||
|
||||
$objs.on('mouseenter', function(e){
|
||||
if($map_body.data('touchMode')){
|
||||
return true;
|
||||
}
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
$tooltip_city.html($this.data('text'));
|
||||
var nation_text = $this.data('nation');
|
||||
if(nation_text){
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
}
|
||||
else{
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
$tooltip.show();
|
||||
});
|
||||
|
||||
$objs.on('mouseleave', function(event){
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
$objs.on('click', function(e){
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
var touchMode = $(this).data('touchMode');
|
||||
if(touchMode === undefined){
|
||||
return;
|
||||
}
|
||||
|
||||
if(touchMode === 1){
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setCityClickable(obj){
|
||||
|
||||
obj.cityList.forEach(function(city){
|
||||
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id));
|
||||
|
||||
if('clickable' in city && city.clickable > 0){
|
||||
$cityLink.attr('href',hrefTemplate.format(city.id));
|
||||
}
|
||||
|
||||
if(selectCallback){
|
||||
$cityLink.click(function(){
|
||||
return selectCallback(city);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function saveCityInfo(obj){
|
||||
$world_map.data('cityInfo', obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
|
||||
if(localStorage.getItem('sam.hideMapCityName') == 'yes'){
|
||||
$world_map.addClass('hide_cityname');
|
||||
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
|
||||
$hideCityNameBtn.click(function(){
|
||||
//이전 상태 확인
|
||||
var state = !$hideCityNameBtn.hasClass('active');
|
||||
if(state){
|
||||
$world_map.addClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'yes');
|
||||
}
|
||||
else{
|
||||
$world_map.removeClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'no');
|
||||
}
|
||||
});
|
||||
|
||||
var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap');
|
||||
if(localStorage.getItem('sam.toggleSingleTap') == 'yes'){
|
||||
window.sam_toggleSingleTap = true;
|
||||
$toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
else{
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
|
||||
var $map_body = $('.world_map .map_body');
|
||||
|
||||
$toggleSingleTapBtn.click(function(){
|
||||
//이전 상태 확인
|
||||
var state = !$toggleSingleTapBtn.hasClass('active');
|
||||
if(state){
|
||||
$map_body.removeData('touchMode');
|
||||
localStorage.setItem('sam.toggleSingleTap', 'yes');
|
||||
window.sam_toggleSingleTap = true;
|
||||
}
|
||||
else{
|
||||
localStorage.setItem('sam.toggleSingleTap', 'no');
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
});
|
||||
|
||||
if(isDetailMap){
|
||||
$world_map.addClass('map_detail');
|
||||
}
|
||||
else{
|
||||
$world_map.removeClass('map_datail');
|
||||
}
|
||||
|
||||
//deferred mode of jQuery. != promise-then.
|
||||
var deferred = $.ajax({
|
||||
url: option.targetJson,
|
||||
type: 'post',
|
||||
dataType:'json',
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
neutralView:option.neutralView,
|
||||
year:option.year,
|
||||
month:option.month,
|
||||
showMe:option.showMe,
|
||||
aux:option.aux
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
deferred
|
||||
.then(checkReturnObject)
|
||||
.then(setMapBackground)
|
||||
.then(convertCityObjs)
|
||||
.then(isDetailMap?drawDetailWorldMap:drawBasicWorldMap)
|
||||
.then(setMouseWork)
|
||||
.then(setCityClickable)
|
||||
.then(saveCityInfo);
|
||||
|
||||
if($world_map.hasClass('draw_required')){
|
||||
if(useCachedMap){
|
||||
//일단 불러옴
|
||||
do{
|
||||
var storedMap = localStorage.getItem(storedOldMapKey);
|
||||
if(!storedMap){
|
||||
break;
|
||||
}
|
||||
storedMap = JSON.parse(storedMap);
|
||||
var storedServerID = storedMap[0];
|
||||
if(storedServerID != serverID){
|
||||
break;
|
||||
}
|
||||
|
||||
storedMap = storedMap[1];
|
||||
storedMap = setMapBackground(storedMap);
|
||||
storedMap = convertCityObjs(storedMap);
|
||||
if(isDetailMap){
|
||||
storedMap = drawDetailWorldMap(storedMap);
|
||||
}
|
||||
else{
|
||||
storedMap = drawBasicWorldMap(storedMap);
|
||||
}
|
||||
storedMap = setMouseWork(storedMap);
|
||||
storedMap = setCityClickable(storedMap);
|
||||
storedMap = saveCityInfo(storedMap);
|
||||
}while(false);
|
||||
}
|
||||
else if(option.year && option.month){
|
||||
var startYear = localStorage.getItem(storedStartYear);
|
||||
if(startYear){
|
||||
startYear = JSON.parse(startYear);
|
||||
}
|
||||
else{
|
||||
startYear = option.year;
|
||||
}
|
||||
var tmp = {
|
||||
year : option.year,
|
||||
month : option.month,
|
||||
startYear : startYear
|
||||
};
|
||||
setMapBackground(tmp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$(function(){
|
||||
if(is_touch_device()){
|
||||
$('.map_body .map_toggle_single_tap').show();
|
||||
}
|
||||
function is_touch_device() {
|
||||
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
var mq = function(query) {
|
||||
return window.matchMedia(query).matches;
|
||||
}
|
||||
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
}
|
||||
|
||||
function reloadWorldMap(option, drawTarget) {
|
||||
if (drawTarget === undefined || drawTarget === null) {
|
||||
drawTarget = '.world_map'
|
||||
}
|
||||
var $world_map = $(drawTarget);
|
||||
|
||||
if ($world_map.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultOption = {
|
||||
isDetailMap: true, //복잡 지도, 단순 지도
|
||||
clickableAll: false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
|
||||
selectCallback: null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
|
||||
hrefTemplate: '#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
|
||||
useCachedMap: false, //맵 캐시를 사용
|
||||
|
||||
//아래부터는 post query에 들어갈 녀석
|
||||
year: null, //year값, 연감등에 사용
|
||||
month: null, //month값, 연감등에 사용
|
||||
aux: null, //기타 넣고 싶은 값을 입력
|
||||
neutralView: false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
|
||||
showMe: true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
|
||||
|
||||
targetJson: 'j_map.php',
|
||||
reqType: 'post',
|
||||
dynamicMapTheme: false,
|
||||
callback: null,
|
||||
|
||||
//기타 보조 값
|
||||
startYear: null,
|
||||
};
|
||||
|
||||
option = $.extend(defaultOption, option);
|
||||
|
||||
var useCachedMap = option.useCachedMap;
|
||||
var isDetailMap = option.isDetailMap;
|
||||
var clickableAll = option.clickableAll;
|
||||
var selectCallback = option.selectCallback;
|
||||
var hrefTemplate = option.hrefTemplate;
|
||||
|
||||
var cityPosition = getCityPosition();
|
||||
|
||||
var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
|
||||
var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
|
||||
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
|
||||
|
||||
function checkReturnObject(obj) {
|
||||
if (!obj.result) {
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if (!$.isNumeric(obj.startYear) ||
|
||||
!$.isNumeric(obj.year) ||
|
||||
!$.isNumeric(obj.month)
|
||||
) {
|
||||
var obj = $.Deferred();
|
||||
obj.reject('fail');
|
||||
return obj.promise();
|
||||
}
|
||||
|
||||
if (useCachedMap) {
|
||||
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
|
||||
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
|
||||
}
|
||||
|
||||
$world_map.removeClass('draw_required');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setMapBackground(obj) {
|
||||
function setTheme() {
|
||||
var oldTheme = $world_map.data('currentTheme');
|
||||
var newTheme = obj.theme;
|
||||
if (oldTheme === newTheme) {
|
||||
return;
|
||||
}
|
||||
if (oldTheme) {
|
||||
$world_map.removeClass('map_theme_' + oldTheme);
|
||||
}
|
||||
$world_map.addClass('map_theme_' + newTheme);
|
||||
$world_map.data('currentTheme', newTheme);
|
||||
}
|
||||
if (option.dynamicMapTheme) {
|
||||
setTheme();
|
||||
}
|
||||
var startYear = obj.startYear;
|
||||
var year = obj.year;
|
||||
var month = obj.month;
|
||||
|
||||
if (isDetailMap) {
|
||||
$world_map.addClass('map_detail').removeClass('map_basic');
|
||||
} else {
|
||||
$world_map.addClass('map_basic').removeClass('map_detail');
|
||||
}
|
||||
|
||||
var $map_title = $('.map_title_text');
|
||||
if (year < startYear + 1) {
|
||||
$map_title.css('color', 'magenta');
|
||||
} else if (year < startYear + 2) {
|
||||
$map_title.css('color', 'orange');
|
||||
} else if (year < startYear + 3) {
|
||||
$map_title.css('color', 'yellow');
|
||||
}
|
||||
|
||||
$map_title_tooltip = $('.map_title .tooltiptext');
|
||||
$map_title_tooltip.empty();
|
||||
|
||||
var tooltipTexts = [];
|
||||
if (year < startYear + 3) {
|
||||
var startYearText = [];
|
||||
var remainYear = startYear + 3 - year;
|
||||
var remainMonth = 12 - month + 1;
|
||||
if (remainMonth > 0) {
|
||||
remainYear -= 1;
|
||||
}
|
||||
if (remainYear) {
|
||||
startYearText.push('{0}년'.format(remainYear));
|
||||
}
|
||||
if (remainMonth) {
|
||||
startYearText.push('{0}개월'.format(remainMonth));
|
||||
}
|
||||
|
||||
tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3));
|
||||
}
|
||||
|
||||
var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1;
|
||||
var nextTechLimitYear = currentTechLimit * 5 + startYear;
|
||||
|
||||
tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit + 1));
|
||||
$map_title_tooltip.html(tooltipTexts.join('<br>'));
|
||||
|
||||
$world_map.removeClass('map_string map_summer map_fall map_winter');
|
||||
if (month <= 3) {
|
||||
$world_map.addClass('map_spring');
|
||||
} else if (month <= 6) {
|
||||
$world_map.addClass('map_summer');
|
||||
} else if (month <= 9) {
|
||||
$world_map.addClass('map_fall');
|
||||
} else {
|
||||
$world_map.addClass('map_winter');
|
||||
}
|
||||
|
||||
$map_title.html('{0}年 {1}月'.format(year, month));
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function convertCityObjs(obj) {
|
||||
//원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다.
|
||||
|
||||
function toCityObj(arr) {
|
||||
return {
|
||||
id: arr[0],
|
||||
level: arr[1],
|
||||
state: arr[2],
|
||||
nationId: (arr[3] > 0) ? arr[3] : null,
|
||||
region: arr[4],
|
||||
supply: (arr[5] != 0)
|
||||
};
|
||||
}
|
||||
|
||||
function toNationObj(arr) {
|
||||
return {
|
||||
id: arr[0],
|
||||
name: arr[1],
|
||||
color: arr[2],
|
||||
capital: arr[3]
|
||||
};
|
||||
}
|
||||
|
||||
var cityList = obj.cityList.map(toCityObj);
|
||||
var nationList = obj.nationList.map(toNationObj);
|
||||
nationList = convertDictById(nationList); //array of object -> dict
|
||||
|
||||
var spyList = obj.spyList;
|
||||
var shownByGeneralList = convertSet(obj.shownByGeneralList); //Array -> Set
|
||||
|
||||
var myCity = obj.myCity;
|
||||
var myNation = obj.myNation;
|
||||
|
||||
|
||||
function mergePositionInfo(city) {
|
||||
var id = city.id;
|
||||
if (!(id in cityPosition)) {
|
||||
return city;
|
||||
}
|
||||
var xy_val = cityPosition[id];
|
||||
city.name = xy_val[0];
|
||||
city.x = xy_val[1];
|
||||
city.y = xy_val[2];
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeNationInfo(city) {
|
||||
//nationId 값으로 isCapital, color, nation을 통합
|
||||
|
||||
var nationId = city.nationId;
|
||||
if (nationId === null || !(nationId in nationList)) {
|
||||
city.nationId = null;
|
||||
city.nation = null;
|
||||
city.color = null;
|
||||
city.isCapital = false;
|
||||
return city;
|
||||
}
|
||||
|
||||
var nationObj = nationList[nationId];
|
||||
city.nation = nationObj.name;
|
||||
city.color = nationObj.color;
|
||||
city.isCapital = (nationObj.capital == city.id);
|
||||
|
||||
return city;
|
||||
}
|
||||
|
||||
function mergeClickable(city) {
|
||||
//clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
|
||||
var id = city.id;
|
||||
var nationId = city.nationId;
|
||||
var clickable = 0;
|
||||
if (id in spyList) {
|
||||
clickable |= spyList[id] << 3;
|
||||
}
|
||||
if (myNation !== null && nationId == myNation) {
|
||||
clickable |= 4;
|
||||
}
|
||||
if (shownByGeneralList.hasOwnProperty(id)) {
|
||||
clickable |= 2;
|
||||
}
|
||||
if (myCity !== null && id == myCity) {
|
||||
clickable |= 2;
|
||||
}
|
||||
if (clickableAll) {
|
||||
clickable |= 1;
|
||||
}
|
||||
|
||||
|
||||
city.clickable = clickable;
|
||||
return city;
|
||||
}
|
||||
|
||||
cityList = cityList
|
||||
.map(mergePositionInfo)
|
||||
.map(mergeNationInfo)
|
||||
.map(mergeClickable)
|
||||
.map(formatCityInfo);
|
||||
|
||||
return {
|
||||
'cityList': cityList,
|
||||
'myCity': myCity
|
||||
};
|
||||
}
|
||||
|
||||
function drawDetailWorldMap(obj) {
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city) {
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
|
||||
|
||||
if ('color' in city && city.color !== null) {
|
||||
var $bgObj = $('<div class="city_bg"></div>');
|
||||
$cityObj.append($bgObj);
|
||||
$bgObj.css({ 'background-image': 'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color)) });
|
||||
}
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level));
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
|
||||
|
||||
if (city.state > 0) {
|
||||
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
|
||||
$linkObj.append($stateObj);
|
||||
}
|
||||
|
||||
if (city.nationId && city.nationId > 0) {
|
||||
var flagType = city.supply ? 'f' : 'd';
|
||||
var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
|
||||
if (city.isCapital) {
|
||||
var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage));
|
||||
$flagObj.append($capitalObj);
|
||||
}
|
||||
$imgObj.append($flagObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
|
||||
$map_body.append($cityObj);
|
||||
|
||||
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function drawBasicWorldMap(obj) {
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
var cityList = obj.cityList;
|
||||
var myCity = obj.myCity;
|
||||
|
||||
cityList.forEach(function(city) {
|
||||
var id = city.id;
|
||||
$('.city_base_{0}'.format(id)).detach();
|
||||
//이전 도시는 지운다.
|
||||
|
||||
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
|
||||
$cityObj.addClass('city_level_{0}'.format(city.level));
|
||||
$cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
|
||||
|
||||
var $linkObj = $('<a class="city_link"></a>');
|
||||
$linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
|
||||
$cityObj.append($linkObj);
|
||||
|
||||
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
|
||||
if ('color' in city && city.color !== null) {
|
||||
$imgObj.css({ 'background-color': city.color });
|
||||
}
|
||||
$linkObj.append($imgObj);
|
||||
|
||||
if (city.state > 0) {
|
||||
var state_text = 'wrong';
|
||||
if (city.state < 10) {
|
||||
state_text = 'good';
|
||||
} else if (city.state < 40) {
|
||||
state_text = 'bad';
|
||||
} else if (city.state < 50) {
|
||||
state_text = 'war';
|
||||
}
|
||||
|
||||
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text));
|
||||
$imgObj.append($stateObj);
|
||||
}
|
||||
|
||||
//단순 표기에서는 깃발 여부가 없음
|
||||
if (city.isCapital) {
|
||||
var $capitalObj = $('<div class="city_capital"></div>');
|
||||
$imgObj.append($capitalObj);
|
||||
}
|
||||
|
||||
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
|
||||
$imgObj.append($nameObj);
|
||||
|
||||
$map_body.append($cityObj);
|
||||
});
|
||||
|
||||
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setMouseWork(obj) {
|
||||
var $tooltip = $(drawTarget + ' .city_tooltip');
|
||||
var $tooltip_city = $tooltip.find('.city_name');
|
||||
var $tooltip_nation = $tooltip.find('.nation_name');
|
||||
|
||||
var $objs = $(drawTarget + ' .city_link');
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
//터치스크린 탭
|
||||
|
||||
if (!option.neutralView && is_touch_device()) {
|
||||
$objs.on('touchstart', function(e) {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if ($tooltip_city.data('target') != $this.data('id')) {
|
||||
$this.data('touchMode', 1);
|
||||
} else if (touchMode === undefined) {
|
||||
$this.data('touchMode', 1);
|
||||
} else {
|
||||
$this.data('touchMode', touchMode + 1);
|
||||
}
|
||||
$map_body.data('touchMode', 1);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
|
||||
|
||||
});
|
||||
|
||||
$objs.on('touchend', function(e) {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
var $this = $(this);
|
||||
var position = $this.parent().position();
|
||||
$tooltip_city.html($this.data('text'));
|
||||
|
||||
var nation_text = $this.data('nation');
|
||||
if (nation_text) {
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
} else {
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
var left = position.left;
|
||||
var top = position.top;
|
||||
|
||||
var scale = $map_body.data('scale');
|
||||
if (scale) {
|
||||
left /= scale;
|
||||
top /= scale;
|
||||
}
|
||||
|
||||
$tooltip.css({ 'top': top + 25, 'left': left + 35 }).show();
|
||||
|
||||
var touchMode = $this.data('touchMode');
|
||||
if (touchMode <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
$this.data('touchMode', 0);
|
||||
});
|
||||
|
||||
$map_body.on('touchend', function(e) {
|
||||
if (window.sam_toggleSingleTap) {
|
||||
return true;
|
||||
}
|
||||
//위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
//Mouse over 모드 작동
|
||||
|
||||
$map_body.on('mousemove', function(e) {
|
||||
if ($(this).data('touchMode')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var rect = this.getBoundingClientRect();
|
||||
var left = (e.clientX - rect.left - this.clientLeft + this.scrollLeft);
|
||||
var top = (e.clientY - rect.top - this.clientTop + this.scrollTop);
|
||||
|
||||
var scale = $map_body.data('scale');
|
||||
if (scale) {
|
||||
left /= scale;
|
||||
top /= scale;
|
||||
}
|
||||
|
||||
$tooltip.css({ 'top': top + 10, 'left': left + 10 });
|
||||
});
|
||||
|
||||
$objs.on('mouseenter', function(e) {
|
||||
if ($map_body.data('touchMode')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$tooltip_city.data('target', $this.data('id'));
|
||||
$tooltip_city.html($this.data('text'));
|
||||
var nation_text = $this.data('nation');
|
||||
if (nation_text) {
|
||||
$tooltip_nation.html(nation_text).show();
|
||||
} else {
|
||||
$tooltip_nation.html('').hide();
|
||||
}
|
||||
|
||||
$tooltip.show();
|
||||
});
|
||||
|
||||
$objs.on('mouseleave', function(event) {
|
||||
$tooltip.hide();
|
||||
});
|
||||
|
||||
$objs.on('click', function(e) {
|
||||
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
|
||||
var touchMode = $(this).data('touchMode');
|
||||
if (touchMode === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (touchMode === 1) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setCityClickable(obj) {
|
||||
|
||||
obj.cityList.forEach(function(city) {
|
||||
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id));
|
||||
|
||||
if ('clickable' in city && city.clickable > 0) {
|
||||
$cityLink.attr('href', hrefTemplate.format(city.id));
|
||||
}
|
||||
|
||||
if (selectCallback) {
|
||||
$cityLink.click(function() {
|
||||
return selectCallback(city);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function saveCityInfo(obj) {
|
||||
$world_map.data('cityInfo', obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
|
||||
if (localStorage.getItem('sam.hideMapCityName') == 'yes') {
|
||||
$world_map.addClass('hide_cityname');
|
||||
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
}
|
||||
|
||||
$hideCityNameBtn.click(function() {
|
||||
//이전 상태 확인
|
||||
var state = !$hideCityNameBtn.hasClass('active');
|
||||
if (state) {
|
||||
$world_map.addClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'yes');
|
||||
} else {
|
||||
$world_map.removeClass('hide_cityname');
|
||||
localStorage.setItem('sam.hideMapCityName', 'no');
|
||||
}
|
||||
});
|
||||
|
||||
var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap');
|
||||
if (localStorage.getItem('sam.toggleSingleTap') == 'yes') {
|
||||
window.sam_toggleSingleTap = true;
|
||||
$toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true');
|
||||
} else {
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
|
||||
var $map_body = $(drawTarget + ' .map_body');
|
||||
|
||||
$toggleSingleTapBtn.click(function() {
|
||||
//이전 상태 확인
|
||||
var state = !$toggleSingleTapBtn.hasClass('active');
|
||||
if (state) {
|
||||
$map_body.removeData('touchMode');
|
||||
localStorage.setItem('sam.toggleSingleTap', 'yes');
|
||||
window.sam_toggleSingleTap = true;
|
||||
} else {
|
||||
localStorage.setItem('sam.toggleSingleTap', 'no');
|
||||
window.sam_toggleSingleTap = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (isDetailMap) {
|
||||
$world_map.addClass('map_detail');
|
||||
} else {
|
||||
$world_map.removeClass('map_datail');
|
||||
}
|
||||
|
||||
//deferred mode of jQuery. != promise-then.
|
||||
var deferred = $.ajax({
|
||||
url: option.targetJson,
|
||||
type: option.reqType,
|
||||
dataType: 'json',
|
||||
ifModified: true,
|
||||
data: {
|
||||
data: JSON.stringify({
|
||||
neutralView: option.neutralView,
|
||||
year: option.year,
|
||||
month: option.month,
|
||||
showMe: option.showMe,
|
||||
aux: option.aux
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
var rawObject = null;
|
||||
|
||||
deferred
|
||||
.then(function(data) {
|
||||
rawObject = data;
|
||||
return data;
|
||||
})
|
||||
.then(checkReturnObject)
|
||||
.then(setMapBackground)
|
||||
.then(convertCityObjs)
|
||||
.then(isDetailMap ? drawDetailWorldMap : drawBasicWorldMap)
|
||||
.then(setMouseWork)
|
||||
.then(setCityClickable)
|
||||
.then(saveCityInfo)
|
||||
.then(function(data) {
|
||||
if (option.callback) {
|
||||
option.callback(data, rawObject);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if ($world_map.hasClass('draw_required')) {
|
||||
if (useCachedMap) {
|
||||
//일단 불러옴
|
||||
do {
|
||||
var storedMap = localStorage.getItem(storedOldMapKey);
|
||||
if (!storedMap) {
|
||||
break;
|
||||
}
|
||||
storedMap = JSON.parse(storedMap);
|
||||
var storedServerID = storedMap[0];
|
||||
if (storedServerID != serverID) {
|
||||
break;
|
||||
}
|
||||
|
||||
storedMap = storedMap[1];
|
||||
storedMap = setMapBackground(storedMap);
|
||||
storedMap = convertCityObjs(storedMap);
|
||||
if (isDetailMap) {
|
||||
storedMap = drawDetailWorldMap(storedMap);
|
||||
} else {
|
||||
storedMap = drawBasicWorldMap(storedMap);
|
||||
}
|
||||
storedMap = setMouseWork(storedMap);
|
||||
storedMap = setCityClickable(storedMap);
|
||||
storedMap = saveCityInfo(storedMap);
|
||||
} while (false);
|
||||
} else if (option.year && option.month) {
|
||||
var startYear = localStorage.getItem(storedStartYear);
|
||||
if (startYear) {
|
||||
startYear = JSON.parse(startYear);
|
||||
} else {
|
||||
startYear = option.year;
|
||||
}
|
||||
var tmp = {
|
||||
year: option.year,
|
||||
month: option.month,
|
||||
startYear: startYear
|
||||
};
|
||||
setMapBackground(tmp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$(function() {
|
||||
if (is_touch_device()) {
|
||||
$('.map_body .map_toggle_single_tap').show();
|
||||
}
|
||||
})
|
||||
@@ -1,232 +1,281 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
require(__DIR__ . '/vendor/autoload.php');
|
||||
|
||||
if (!class_exists('\\sammo\\RootDB')) {
|
||||
header('Location:install.php');
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
$session = Session::getInstance();
|
||||
|
||||
use \kakao\KakaoKey as KakaoKey;
|
||||
|
||||
if ($session->isLoggedIn()) {
|
||||
header('Location:i_entrance/entrance.php');
|
||||
die();
|
||||
}
|
||||
|
||||
?>
|
||||
<!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>삼국지 모의전투 HiDCHe</title>
|
||||
<?= 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/login.js') ?>
|
||||
<?= WebUtil::printCSS('e_lib/bootstrap.min.css') ?>
|
||||
<?= WebUtil::printCSS('css/login.css') ?>
|
||||
<meta name="description" content="실시간으로 진행되는 삼국지 웹게임(삼모전)입니다">
|
||||
<meta name="keywords" content="삼국지,삼모전,웹게임,힏체,힏체섭,히데체,히데체섭,HiDCHe,체섭">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="삼국지 모의전투 HiDCHe">
|
||||
<meta property="og:description" content="실시간으로 진행되는 삼국지 웹게임(삼모전)입니다">
|
||||
<meta property="og:url" content="https://sam.hided.net">
|
||||
<script>
|
||||
var oauthMode = null;
|
||||
|
||||
function getOAuthToken(mode, scope_list) {
|
||||
if (mode === undefined) {
|
||||
mode = 'login';
|
||||
}
|
||||
if (scope_list === undefined) {
|
||||
scope_list = null;
|
||||
}
|
||||
oauthMode = mode;
|
||||
var url = 'https://kauth.kakao.com/oauth/authorize?' +
|
||||
'client_id=<?= KakaoKey::REST_KEY ?>&' +
|
||||
'redirect_uri=<?= KakaoKey::REDIRECT_URI ?>&' +
|
||||
'response_type=code';
|
||||
if (Array.isArray(scope_list)) {
|
||||
url += '&scope=' + scope_list.join(',');
|
||||
} else if (typeof scope_list === 'string' || scope_list instanceof String) {
|
||||
url += '&scope=' + scope_list;
|
||||
}
|
||||
|
||||
window.open(url, "KakaoAccountLogin", "width=600,height=450,resizable=yes,scrollbars=yes");
|
||||
}
|
||||
|
||||
function sendTempPasswordToKakaoTalk() {
|
||||
$.post({
|
||||
url: 'oauth_kakao/j_login_oauth.php',
|
||||
dataType: 'json'
|
||||
}).then(function(obj) {
|
||||
var t = $.Deferred();
|
||||
if (!obj.result) {
|
||||
t.reject();
|
||||
}
|
||||
return $.post({
|
||||
url: 'oauth_kakao/j_change_pw.php',
|
||||
dataType: 'json'
|
||||
});
|
||||
}).then(function(obj) {
|
||||
if (!obj.result) {
|
||||
alert(obj.reason);
|
||||
} else {
|
||||
alert('임시 비밀번호가 카카오톡으로 전송되었습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function doLoginUsingOAuth() {
|
||||
$.post({
|
||||
url: 'oauth_kakao/j_login_oauth.php',
|
||||
dataType: 'json'
|
||||
}).then(function(obj) {
|
||||
if (obj.result) {
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
if (!obj.reqOTP) {
|
||||
alert(obj.reason);
|
||||
return;
|
||||
}
|
||||
$('#modalOTP').modal().on('shown.bs.modal', function() {
|
||||
$('#otp_code').focus();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function postOAuthResult(result) {
|
||||
if (result == 'join') {
|
||||
window.location.href = 'oauth_kakao/join.php';
|
||||
} else if (result == 'req_email') {
|
||||
alert('이메일 정보 공유를 허가해 주셔야 합니다.');
|
||||
} else if (result == 'login') {
|
||||
console.log('로그인모드');
|
||||
if (oauthMode == 'change_pw') {
|
||||
sendTempPasswordToKakaoTalk();
|
||||
} else {
|
||||
doLoginUsingOAuth();
|
||||
}
|
||||
} else {
|
||||
alert('예외 발생!');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href=".">삼국지 모의전투 HiDCHe</a>
|
||||
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<?= WebUtil::drawMenu(ROOT . '/d_shared/menu.json') ?>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="full-content">
|
||||
<div class="vertical-center">
|
||||
<div class="container">
|
||||
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe</h1>
|
||||
<div class="row justify-content-md-center">
|
||||
<div class="col" style="max-width:450px;">
|
||||
<div class="card" id="login_card">
|
||||
<h3 class="card-header">
|
||||
로그인
|
||||
</h3>
|
||||
<div class="card-body">
|
||||
|
||||
<form id="main_form" method="post" action="#">
|
||||
<div class="form-group row">
|
||||
<label for="username" class="col-5 col-md-4 col-form-label">계정명</label>
|
||||
<div class="col-7 col-md-8">
|
||||
<input autocomplete="username" type="text" class="form-control" name="username" id="username" autofocus="autofocus" placeholder="계정명" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="password" class="col-5 col-md-4 col-form-label">비밀번호</label>
|
||||
<div class="col-7 col-md-8">
|
||||
<input autocomplete="current-password" type="password" class="form-control" name="password" id="password" placeholder="비밀번호" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="global_salt" name="global_salt" value="<?= RootDB::getGlobalSalt() ?>">
|
||||
<div class="form-group row">
|
||||
<div class="col-5 col-md-4 " style="position:relative;"><button type="button" onclick="getOAuthToken('login', ['account_email','talk_message']);" id="btn_kakao_login" title="카카오톡으로 가입&로그인"></button></div>
|
||||
<div class="col-7 col-md-8">
|
||||
<div class="btn-group btn-group-lg d-flex login_btn_group" role="group">
|
||||
<button type="submit" class="btn btn-primary login-button w-100">로그인</button>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> </button>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="btnGroupDrop1">
|
||||
<a class="dropdown-item" href="javascript:getOAuthToken('change_pw', 'talk_message');">비밀번호 초기화</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom_box">
|
||||
<div class="container"><a href="terms.2.html">개인정보처리방침</a> & <a href="terms.1.html">이용약관</a><br>© 2020 • HideD
|
||||
<br>크롬과 파이어폭스에 최적화되어있습니다.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modalOTP" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<form id="otp_form" method="post" action="#">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">인증 코드 필요</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
인증 코드가 필요합니다.<br><br>
|
||||
카카오톡의 '나와의 채팅'란을 확인해 주세요.<br>
|
||||
(별도의 알림[소리, 진동, 숫자]이 발생하지 않습니다.)
|
||||
</div>
|
||||
<div class="input-group mt-4" role="group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">인증 코드</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name='otp' id="otp_code" placeholder="인증 코드">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">취소</button>
|
||||
<button type="submit" class="btn btn-primary">제출</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
require(__DIR__ . '/vendor/autoload.php');
|
||||
|
||||
if (!class_exists('\\sammo\\RootDB')) {
|
||||
header('Location:install.php');
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
$session = Session::getInstance();
|
||||
|
||||
use \kakao\KakaoKey as KakaoKey;
|
||||
|
||||
if ($session->isLoggedIn()) {
|
||||
header('Location:i_entrance/entrance.php');
|
||||
die();
|
||||
}
|
||||
|
||||
$runningServer = null;
|
||||
|
||||
foreach(ServConfig::getServerList() as $setting){
|
||||
if(!$setting->isExists()){
|
||||
continue;
|
||||
}
|
||||
if(!$setting->isRunning()){
|
||||
continue;
|
||||
}
|
||||
$runningServer = [
|
||||
'color'=>$setting->getColor(),
|
||||
'korName'=>$setting->getKorName(),
|
||||
'name'=>$setting->getShortName(),
|
||||
'exists'=>$setting->isExists(),
|
||||
'enable'=>$setting->isRunning()
|
||||
];
|
||||
}
|
||||
|
||||
if($runningServer){
|
||||
$subTemplates = new \League\Plates\Engine(__DIR__.'/'.$runningServer['name'].'/templates');
|
||||
}
|
||||
|
||||
?>
|
||||
<!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>삼국지 모의전투 HiDCHe</title>
|
||||
<script>
|
||||
var runningServer = <?=Json::encode($runningServer)?>;
|
||||
</script>
|
||||
<?= 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/login.js') ?>
|
||||
<?= WebUtil::printJS('d_shared/common_path.js') ?>
|
||||
<?= WebUtil::printCSS('d_shared/common.css') ?>
|
||||
<?= WebUtil::printCSS('e_lib/bootstrap.min.css') ?>
|
||||
<?= WebUtil::printCSS('css/login.css') ?>
|
||||
<?php if($runningServer): ?>
|
||||
<script>
|
||||
var serverNick = '<?=$runningServer['korName']?>';
|
||||
</script>
|
||||
<?= WebUtil::printJS($runningServer['name'].'/d_shared/base_map.js') ?>
|
||||
<?= WebUtil::printJS($runningServer['name'].'/js/map.js') ?>
|
||||
<?= WebUtil::printCSS($runningServer['name'].'/css/map.css') ?>
|
||||
<?php endif; ?>
|
||||
<meta name="description" content="실시간으로 진행되는 삼국지 웹게임(삼모전)입니다">
|
||||
<meta name="keywords" content="삼국지,삼모전,웹게임,힏체,힏체섭,히데체,히데체섭,HiDCHe,체섭">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="삼국지 모의전투 HiDCHe">
|
||||
<meta property="og:description" content="실시간으로 진행되는 삼국지 웹게임(삼모전)입니다">
|
||||
<meta property="og:url" content="https://sam.hided.net">
|
||||
<script>
|
||||
var oauthMode = null;
|
||||
|
||||
function getOAuthToken(mode, scope_list) {
|
||||
if (mode === undefined) {
|
||||
mode = 'login';
|
||||
}
|
||||
if (scope_list === undefined) {
|
||||
scope_list = null;
|
||||
}
|
||||
oauthMode = mode;
|
||||
var url = 'https://kauth.kakao.com/oauth/authorize?' +
|
||||
'client_id=<?= KakaoKey::REST_KEY ?>&' +
|
||||
'redirect_uri=<?= KakaoKey::REDIRECT_URI ?>&' +
|
||||
'response_type=code';
|
||||
if (Array.isArray(scope_list)) {
|
||||
url += '&scope=' + scope_list.join(',');
|
||||
} else if (typeof scope_list === 'string' || scope_list instanceof String) {
|
||||
url += '&scope=' + scope_list;
|
||||
}
|
||||
|
||||
window.open(url, "KakaoAccountLogin", "width=600,height=450,resizable=yes,scrollbars=yes");
|
||||
}
|
||||
|
||||
function sendTempPasswordToKakaoTalk() {
|
||||
$.post({
|
||||
url: 'oauth_kakao/j_login_oauth.php',
|
||||
dataType: 'json'
|
||||
}).then(function(obj) {
|
||||
var t = $.Deferred();
|
||||
if (!obj.result) {
|
||||
t.reject();
|
||||
}
|
||||
return $.post({
|
||||
url: 'oauth_kakao/j_change_pw.php',
|
||||
dataType: 'json'
|
||||
});
|
||||
}).then(function(obj) {
|
||||
if (!obj.result) {
|
||||
alert(obj.reason);
|
||||
} else {
|
||||
alert('임시 비밀번호가 카카오톡으로 전송되었습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function doLoginUsingOAuth() {
|
||||
$.post({
|
||||
url: 'oauth_kakao/j_login_oauth.php',
|
||||
dataType: 'json'
|
||||
}).then(function(obj) {
|
||||
if (obj.result) {
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
if (!obj.reqOTP) {
|
||||
alert(obj.reason);
|
||||
return;
|
||||
}
|
||||
$('#modalOTP').modal().on('shown.bs.modal', function() {
|
||||
$('#otp_code').focus();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function postOAuthResult(result) {
|
||||
if (result == 'join') {
|
||||
window.location.href = 'oauth_kakao/join.php';
|
||||
} else if (result == 'req_email') {
|
||||
alert('이메일 정보 공유를 허가해 주셔야 합니다.');
|
||||
} else if (result == 'login') {
|
||||
console.log('로그인모드');
|
||||
if (oauthMode == 'change_pw') {
|
||||
sendTempPasswordToKakaoTalk();
|
||||
} else {
|
||||
doLoginUsingOAuth();
|
||||
}
|
||||
} else {
|
||||
alert('예외 발생!');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href=".">삼국지 모의전투 HiDCHe</a>
|
||||
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<?= WebUtil::drawMenu(ROOT . '/d_shared/menu.json') ?>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container" style="margin-top:120px;">
|
||||
<h1 class="row justify-content-md-center">삼국지 모의전투 HiDCHe</h1>
|
||||
<div class="row justify-content-md-center">
|
||||
<div class="col" style="max-width:450px;">
|
||||
<div class="card" id="login_card">
|
||||
<h3 class="card-header">
|
||||
로그인
|
||||
</h3>
|
||||
<div class="card-body">
|
||||
|
||||
<form id="main_form" method="post" action="#">
|
||||
<div class="form-group row">
|
||||
<label for="username" class="col-5 col-md-4 col-form-label">계정명</label>
|
||||
<div class="col-7 col-md-8">
|
||||
<input autocomplete="username" type="text" class="form-control" name="username" id="username" autofocus="autofocus" placeholder="계정명" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="password" class="col-5 col-md-4 col-form-label">비밀번호</label>
|
||||
<div class="col-7 col-md-8">
|
||||
<input autocomplete="current-password" type="password" class="form-control" name="password" id="password" placeholder="비밀번호" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" id="global_salt" name="global_salt" value="<?= RootDB::getGlobalSalt() ?>">
|
||||
<div class="form-group row">
|
||||
<div class="col-5 col-md-4 " style="position:relative;"><button type="button" onclick="getOAuthToken('login', ['account_email','talk_message']);" id="btn_kakao_login" title="카카오톡으로 가입&로그인"></button></div>
|
||||
<div class="col-7 col-md-8">
|
||||
<div class="btn-group btn-group-lg d-flex login_btn_group" role="group">
|
||||
<button type="submit" class="btn btn-primary login-button w-100">로그인</button>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> </button>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="btnGroupDrop1">
|
||||
<a class="dropdown-item" href="javascript:getOAuthToken('change_pw', 'talk_message');">비밀번호 초기화</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if($runningServer): ?>
|
||||
<div class="row justify-content-md-center" id="running_map">
|
||||
<div class="col" style="max-width:700px;">
|
||||
<div class="card" style="width:700px;">
|
||||
<h3 class="card-header">
|
||||
<?=$runningServer['korName']?> 현황
|
||||
</h3>
|
||||
<div class='map-container' style='position:relative;'>
|
||||
<?=$subTemplates->render('map', [
|
||||
'mapTheme' => ''
|
||||
])?>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div id="bottom_box">
|
||||
<div class="container"><a href="terms.2.html">개인정보처리방침</a> & <a href="terms.1.html">이용약관</a><br>© 2020 • HideD
|
||||
<br>크롬과 파이어폭스에 최적화되어있습니다.</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modalOTP" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<form id="otp_form" method="post" action="#">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">인증 코드 필요</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
인증 코드가 필요합니다.<br><br>
|
||||
카카오톡의 '나와의 채팅'란을 확인해 주세요.<br>
|
||||
(별도의 알림[소리, 진동, 숫자]이 발생하지 않습니다.)
|
||||
</div>
|
||||
<div class="input-group mt-4" role="group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">인증 코드</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name='otp' id="otp_code" placeholder="인증 코드">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">취소</button>
|
||||
<button type="submit" class="btn btn-primary">제출</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+117
-93
@@ -1,93 +1,117 @@
|
||||
$(document).ready( function () {
|
||||
$( "#main_form" ).validate( {
|
||||
rules: {
|
||||
username: {
|
||||
required: true
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
username: {
|
||||
required: "유저명을 입력해주세요"
|
||||
},
|
||||
password: {
|
||||
required: "비밀번호를 입력해주세요"
|
||||
}
|
||||
},
|
||||
errorElement: "div",
|
||||
errorPlacement: function ( error, element ) {
|
||||
// Add the `help-block` class to the error element
|
||||
error.addClass( "invalid-feedback" );
|
||||
|
||||
if ( element.prop( "type" ) === "checkbox" ) {
|
||||
error.insertAfter( element.parent( "label" ) );
|
||||
} else {
|
||||
error.insertAfter( element );
|
||||
}
|
||||
},
|
||||
highlight: function ( element, errorClass, validClass ) {
|
||||
$( element ).addClass( "is-invalid" ).removeClass( "is-valid" );
|
||||
},
|
||||
unhighlight: function (element, errorClass, validClass) {
|
||||
$( element ).addClass( "is-valid" ).removeClass( "is-invalid" );
|
||||
}
|
||||
} );
|
||||
|
||||
$( "#main_form" ).submit(function(){
|
||||
var raw_password = $('#password').val();
|
||||
var salt = $('#global_salt').val();
|
||||
var hash_pw = sha512(salt + raw_password + salt);
|
||||
|
||||
$.post({
|
||||
url:'j_login.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
'username':$('#username').val(),
|
||||
'password':hash_pw
|
||||
}
|
||||
}).then(function(obj){
|
||||
if(obj.result){
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
if(!obj.reqOTP){
|
||||
alert(obj.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
var $modal = $('#modalOTP').modal();
|
||||
$modal.on('shown.bs.modal', function(){
|
||||
$('#otp_code').focus();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#otp_form').submit(function(){
|
||||
$.post({
|
||||
url:'oauth_kakao/j_check_OTP.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
'otp':$('#otp_code').val(),
|
||||
}
|
||||
}).then(function(obj){
|
||||
if(obj.result){
|
||||
alert(obj.reason);
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
|
||||
alert(obj.reason);
|
||||
|
||||
if(obj.reset){
|
||||
$('#modalOTP').modal('hide')
|
||||
return;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
})
|
||||
} );
|
||||
$(document).ready(function() {
|
||||
$("#main_form").validate({
|
||||
rules: {
|
||||
username: {
|
||||
required: true
|
||||
},
|
||||
password: {
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
username: {
|
||||
required: "유저명을 입력해주세요"
|
||||
},
|
||||
password: {
|
||||
required: "비밀번호를 입력해주세요"
|
||||
}
|
||||
},
|
||||
errorElement: "div",
|
||||
errorPlacement: function(error, element) {
|
||||
// Add the `help-block` class to the error element
|
||||
error.addClass("invalid-feedback");
|
||||
|
||||
if (element.prop("type") === "checkbox") {
|
||||
error.insertAfter(element.parent("label"));
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
highlight: function(element, errorClass, validClass) {
|
||||
$(element).addClass("is-invalid").removeClass("is-valid");
|
||||
},
|
||||
unhighlight: function(element, errorClass, validClass) {
|
||||
$(element).addClass("is-valid").removeClass("is-invalid");
|
||||
}
|
||||
});
|
||||
|
||||
$("#main_form").submit(function() {
|
||||
var raw_password = $('#password').val();
|
||||
var salt = $('#global_salt').val();
|
||||
var hash_pw = sha512(salt + raw_password + salt);
|
||||
|
||||
$.post({
|
||||
url: 'j_login.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'username': $('#username').val(),
|
||||
'password': hash_pw
|
||||
}
|
||||
}).then(function(obj) {
|
||||
if (obj.result) {
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
if (!obj.reqOTP) {
|
||||
alert(obj.reason);
|
||||
return;
|
||||
}
|
||||
|
||||
var $modal = $('#modalOTP').modal();
|
||||
$modal.on('shown.bs.modal', function() {
|
||||
$('#otp_code').focus();
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#otp_form').submit(function() {
|
||||
$.post({
|
||||
url: 'oauth_kakao/j_check_OTP.php',
|
||||
dataType: 'json',
|
||||
data: {
|
||||
'otp': $('#otp_code').val(),
|
||||
}
|
||||
}).then(function(obj) {
|
||||
if (obj.result) {
|
||||
alert(obj.reason);
|
||||
window.location.href = "./";
|
||||
return;
|
||||
}
|
||||
|
||||
alert(obj.reason);
|
||||
|
||||
if (obj.reset) {
|
||||
$('#modalOTP').modal('hide')
|
||||
return;
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
if (document.body.clientWidth < 700) {
|
||||
var targetWidth = document.body.clientWidth * 0.9;
|
||||
var scale = targetWidth / 700;
|
||||
var $map = $('#running_map');
|
||||
$map.find('.col').css('max-width', targetWidth);
|
||||
$map.find('.card').css('width', targetWidth);
|
||||
$map.find('.map-container').css({
|
||||
'transform-origin': 'top left',
|
||||
'transform': 'scale({0}, {0})'.format(scale),
|
||||
'height': 500 * scale,
|
||||
});
|
||||
$map.find('.map_body').data('scale', scale);
|
||||
}
|
||||
|
||||
reloadWorldMap({
|
||||
targetJson: "{0}/j_map_recent.php".format(runningServer.name),
|
||||
reqType: 'get',
|
||||
dynamicMapTheme: true,
|
||||
callback: function(data, rawObject) {
|
||||
$('#running_map .card-body').html(rawObject.history);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user