2014-03-29 2 views
2

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; 
} 

답변

1

것은 내가 잘못 생각하는 경우 정정 해줘,하지만 당신은 바인딩의 기능을 실행한다. 다음과 같이 지정하십시오.

$(window).bind('hashchange', onHashchange).trigger('hashchange'); 

'()'이 (가) 뒤에 없습니다.

일부 브라우저에서는 지원이 제한되어 있습니다.

발췌에서 : jQuery - hashchange event

if (("onhashchange" in window) && !($.browser.msie)) { 
    window.onhashchange = function() { 
      alert(window.location.hash);    
    }    
    // Or $(window).bind('hashchange',function(e) { 
    //  alert(window.location.hash); 
    // });    
} 
else { 
    var prevHash = window.location.hash; 
    window.setInterval(function() { 
     if (window.location.hash != prevHash) { 
      prevHash = window.location.hash; 
      alert(window.location.hash); 
     } 
    }, 100); 
} 

사용자의 필요에 따라 적응.

+0

당신이 제안한 링크를 읽었습니다. 실제로 "console.log ('SUPPORTED') 로깅을 테스트하고 있습니다.".. 나는 가능한 한 빨리 여분의 부모를 제거하려고 노력할 것입니다. 그것이 실수인지 알려주십시오. 도움을 위해 미리 감사드립니다 =) – LMG

+0

완벽! 도와 주셔서 감사합니다! 괄호가 잘못된 위치에 있었을 때, 어떻게 거기에 넣었는지 모르겠다. 도와 줘서 고마워, 지금해야하는대로 일하고있다! – LMG

관련 문제