SPA에 대해 이야기하는 책을 읽으려고합니다 - 단일 페이지 웹 응용 프로그램입니다. 매우 흥미 롭지 만 코드 조각에 막혀 있습니다. 지금까지 나는 내가하는 일이 무엇인지 알고 있었기 때문에 이것이 이상하게 보입니다.간단한 스파에서 jquery로 hashchange 이벤트가 트리거되지 않았습니다.
채팅 클릭시 트리거되는 이벤트가 페이지 오른쪽 하단에 있습니다. 이 이벤트는 URL 해시의 변경을 트리거하지만 .. 창이 연결된 경우에도 해시 변경 이벤트가 발생하지 않습니다. $(window).bind('hashchange', onHashchange()).trigger('hashchange');
채팅을 열 때마다 수동으로 새로 고침해야합니다. onhashchange
에 의해 트리거되기를 원하기 때문에 이런 일이 일어나지 않아야합니다. 무슨 일이 일어나는지 알아볼 수 있습니까?
내가 뭔가를 놓친 것 같아,하지만,이 경우에는 단지 작동하지 않는 동안 모든 사람들이 주위에 대한 다른 브라우저와의 호환성에서 작동하지 않는 불평 : S
모든 힌트 감사합니다 =)
다음과 같은 html 코드가 있습니다
<html>
<head>
<title>SPA starter</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/spa.css" type="text/css">
<link rel="stylesheet" href="css/spa.shell.css" type="text/css">
<!-- 3rd party lib -->
<script id="jquery_js" src="js/libs/jquery/jquery.js"></script>
<script id="janchor_js" src="js/libs/jquery/jquery.uriAnchor.js"></script>
<!-- my lib -->
<script id ="spajs" src="js/spa.js"></script>
<script id="spashelljs" src="js/spa.shell.js"></script>
<script id="unloader" src="js/js_unloader.js"></script>
<script id="starter">
$(function() {
spa.initModule($('#spa'));
});
</script>
</head>
<body>
<div id="spa"></div>
</body>
</html>
및 3 개의 스크립트 + jquery가 있습니다. 첫 번째 스크립트는 다른 두가
spa.js
var spa = (function() {
var initModule = function($container) {
spa.shell.initModule($container);
};
return {initModule: initModule};
}());
spa.shell.js
spa.shell = (function() {
//----------- BEGIN MODULE SCOPE VARIABLES ---------
var configMap = {
main_html: String() +
'<div class="spa-shell-head">' +
'<div class="spa-shell-head-logo"> </div>' +
'<div class="spa-shell-head-acct"> </div>' +
'<div class="spa-shell-head-search"> </div>' +
'</div>' +
'<div class="spa-shell-main">' +
' <div class="spa-shell-main-nav"> </div>' +
' <div class="spa-shell-main-content"> </div>' +
'</div>' +
'<div class="spa-shell-foot"></div>' +
'<div class="spa-shell-chat"></div>' +
'<div class="spa-shell-modal"></div>',
chat_extend_time: 250,
chat_retract_time: 300,
chat_extend_height: 450,
chat_retract_height: 15,
chat_extended_title: 'Click to retract',
chat_retracted_title: 'Click to extend',
anchor_schema_map: {
chat: {open: true, closed: true}
}
},
stateMap = {
$container: null,
is_chat_retracted: true,
anchor_map: {}
},
jqueryMap = {},
setJqueryMap, toogleChat, onClickChat,
copyAnchorMap, changeAnchorPart, onHashchange,
initModule;
//----------- END MODULE SCOPE VARIABLES ---------
//----------- BEGIN UTILITY METHODS ---------
//Return copy of stored anchro map; minimizes overhead
copyAnchorMap = function() {
return $.extend(true, {}, stateMap.anchor_map);
};
//----------- END UTILITY METHODS ---------
//----------- BEGIN DOM METHODS ---------
//Begin DOM method /changeAnchorPart/
changeAnchorPart = function(arg_map) {
console.log("change anchor part");
var
anchor_map_revise = copyAnchorMap(),
bool_return = true,
key_name, key_name_dep;
//BEGIN merge changes into anchor map
KEYVAL:
for (key_name in arg_map) {
if (arg_map.hasOwnProperty(key_name)) {
//console.log("key_name:= " + key_name);
//skip dependet keys during iteration
if (key_name.indexOf('_') === 0) {
console.log("key name starts with '_'");
continue KEYVAL;
}
//update independent key value
anchor_map_revise[key_name] = arg_map[key_name];
//update matching dependent key
key_name_dep = '_' + key_name;
//console.log("key_name_dep:= " + key_name_dep);
if (arg_map[key_name_dep]) {
//console.log("if");
anchor_map_revise[key_name_dep] = arg_map[key_name_dep];
}
else {
//console.log("else");
delete anchor_map_revise[key_name_dep];
delete anchor_map_revise['_s' + key_name_dep];
}
}
}
//END merge changes into anchor map
//BEGIN ateempt to update URI; revert if not successful
try {
console.log("setting anchor");
$.uriAnchor.setAnchor(anchor_map_revise);
console.log("set");
} catch (error) {
//replace URI with existing state
$.uriAnchor.setAnchor(stateMap.anchor_map, null, true);
console.log("changeAnchorPart error :=" + error);
bool_return = false;
}
//END attemp to update URI
return bool_return;
};
//END DOM method /changeAnchorPart/
//begin DOM method /setJqueryMap/
setJqueryMap = function() {
var $container = stateMap.$container;
jqueryMap = {$container: $container,
$chat: $container.find('.spa-shell-chat')
};
};
//end DOM method /setJqueryMap/
//Begin DOM method /toogleChat/
//
toogleChat = function(do_extend, callback) {
var px_chat_ht = jqueryMap.$chat.height(),
is_open = px_chat_ht === configMap.chat_extend_height,
is_closed = px_chat_ht === configMap.chat_retract_height,
is_sliding = !is_open && !is_closed;
//avoid race condition
if (is_sliding) {
console.log('avoid race condition');
return false;
}
//begin chat slider
if (do_extend) {
jqueryMap.$chat.animate({height: configMap.chat_extend_height},
configMap.chat_extend_time, function() {
jqueryMap.$chat.attr('title', configMap.chat_extended_title);
stateMap.is_chat_retracted = false;
if (callback) {
callback(jqueryMap.$chat);
}
});
return true;
}
//End extend chat slider
//Begin retract chat slider
jqueryMap.$chat.animate({height: configMap.chat_retract_height},
configMap.chat_retract_time, function() {
jqueryMap.$chat.attr('title', configMap.chat_retracted_title);
stateMap.is_chat_retracted = true;
if (callback) {
callback(jqueryMap.$chat)
}
});
return true;
//End rectract chat slider
};
//end DOM method /toogleChat/
//----------- END DOM METHODS ---------
//
//----------- BEGIN EVENT HANDLERS ---------
onClickChat = function(event) {
// console.log(stateMap.is_chat_retracted);
changeAnchorPart({
chat: (stateMap.is_chat_retracted ? 'open' : 'closed')
});
return false;
};
//
// BEGIN event handler /onHashchange/
//
onHashchange = function(event) {
console.log("on hash change");
var
anchor_map_previous = copyAnchorMap(),
anchor_map_proposed,
_s_chat_previous, _s_chat_proposed,
s_chat_proposed;
//Attempt to parse anchor
try {
anchor_map_proposed = $.uriAnchor.makeAnchorMap();
} catch (error) {
console.log("onHashchange error:= " + error)
$.uriAnchor.setAnchor(anchor_map_previous, null, true);
return false;
}
stateMap.anchor_map = anchor_map_proposed;
//convenience vars
_s_chat_previous = anchor_map_previous._s_chat;
_s_chat_proposed = anchor_map_proposed._s_chat;
//BEGIN adjust of component if changed
if (!anchor_map_previous || _s_chat_previous !== _s_chat_proposed) {
s_chat_proposed = anchor_map_proposed.chat;
console.log("adjusting components, chat:= " + s_chat_proposed);
switch (s_chat_proposed) {
case 'open':
toogleChat(true);
break;
case 'closed':
toogleChat(false);
break;
default :
toogleChat(false);
delete anchor_map_proposed.chat;
$.uriAnchor.setAnchor(anchor_map_proposed, null, true);
}
}
//END of the adjustment
return false;
};
//END event handler /onHashchange/
//----------- END EVENT HANDLERS ---------
//----------- BEGIN PUBLIC METHODS ---------
//Begin Public methods /initModule/
//
initModule = function($container) {
//load HTML and map jQuery collections
stateMap.$container = $container;
$container.html(configMap.main_html);
setJqueryMap();
//initialize chat slider and bind click handler
stateMap.is_chat_retracted = true;
jqueryMap.$chat.attr('title', configMap.chat_retracted_title)
.click(onClickChat);
//configure uriAnchor to use our schema
$.uriAnchor.configModule({
schema_map: configMap.anchor_schema_map
});
//HANDLE URI anchor change events
//
if ("onhashchange" in window) {
console.log('SUPPORTED');
}
$(window).bind('hashchange', onHashchange()).trigger('hashchange');
};
//End PUBLIC methods /initModule/
return {initModule: initModule};
//----------- END PUBLIC METHODS ---------
}());
spa.css
를 따르고 있습니다, 여기 and is provided by the author of the book 찾을 수 있습니다*{
margin : 0;
padding : 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
h1,h2,h3,h4,h5,h6, p{ margin-bottom: 10px;}
o1,ul,dl{list-style-position: inside;}
/** end reset */
/** begin standard selectors */
body{
font: 13px 'Trebuchet MS', Verdana, Helvetica, Arial, sans-serif;
color: #444;
background-color: #888;
}
strong{
font-weight: 800;
color:#000;
}
/** end standard selectors */
/** begin spa namespace selectors */
#spa{
position: absolute;
top:8px;
left:8px;
bottom:8px;
right:8px;
min-height: 500px;
min-width: 500px;
overflow: hidden;
border-radius: 0 8px 0 8px;
background-color: #fff;
}
/** end spa namespace selectors */
/** begin utility selectors */
.spa-x-select{}
.spa-x-clearfloat{
height: 0 !important;
float: none !important;
visibility: hidden !important;
clear: both !important;
}
/** */
spa.shell.css
.spa-shell-head, .spa-shell-head-logo, .spa-shell-head-acct, .spa-shell-head-search,
.spa-shell-main, .spa-shell-main-content, .spa-shell-main-nav, .spa-shell-foot,
.spa-shell-chat, .spa-shell-modal {
position: absolute;
}
.spa-shell-head{
top:0;
left:0;
right:0;
height: 40px;
background-color: red;
}
.spa-shell-head-logo{
top: 4px;
left: 4px;
height: 32px;
width: 128px;
background: orange;
}
.spa-shell-head-acct{
top:4px;
right:0;
width: 64px;
height: 32px;
background: green;
}
.spa-shell-head-search{
top:4px;
right:64px;
width: 248px;
height: 32px;
background: blue;
}
.spa-shell-main{
top:40px;
left:0;
bottom:40px;
right:0;
background-color: #993300;
}
.spa-shell-main-content, .spa-shell-main-nav{
top:0;
bottom:0;
}
.spa-shell-main-nav{
width:250px;
background: #eee;
}
.spa-x-closed, .spa-shell-main-nav{
width:0;
}
.spa-shell-main-content{
left:250px;
right:0;
background: #ddd;
}
.spa-x-closed .spa-shell-main-content{
left:0;
}
.spa-shell-foot{
bottom:0;
left:0;
right:0;
height:40px;
background-color: #99ffff;
}
.spa-shell-chat{
bottom:0;
right:0;
width: 300px;
height: 15px;
background: burlywood;
z-index: 1;
cursor:pointer;
border-radius: 5px 0 0 0;
}
.spa-shell-modal{
margin-top:-200px;
margin-left:-200px;
top:50%;
left:50%;
width:400px;
height:400px;
background: #fff;
border-radius: 3px;
z-index: 2;
}
당신이 제안한 링크를 읽었습니다. 실제로 "console.log ('SUPPORTED') 로깅을 테스트하고 있습니다.".. 나는 가능한 한 빨리 여분의 부모를 제거하려고 노력할 것입니다. 그것이 실수인지 알려주십시오. 도움을 위해 미리 감사드립니다 =) – LMG
완벽! 도와 주셔서 감사합니다! 괄호가 잘못된 위치에 있었을 때, 어떻게 거기에 넣었는지 모르겠다. 도와 줘서 고마워, 지금해야하는대로 일하고있다! – LMG