Commit a4ac7568a0487233202437722c682eef9a0e0016

Authored by Leonardo Merlin
1 parent 1fbebcd3

Fix #41 - Router em URL com HASH e HistoryAPI

@@ -24,13 +24,17 @@ @@ -24,13 +24,17 @@
24 </header> 24 </header>
25 25
26 <div id="content"> 26 <div id="content">
27 - {{{article.body}}} 27 + <p>{{{article.body}}}</p>
28 </div> 28 </div>
29 29
30 <nav> 30 <nav>
31 <ul> 31 <ul>
32 - <li id='nav-proposal-categories'><a href="#proposal-categories" class="active">Temas</a></li>  
33 - <li id='nav-proposal-group'><a href="#proposal-group">Programas</a></li> 32 + <li id='nav-proposal-categories'>
  33 + <a href="#/temas" class="active">Temas</a>
  34 + </li>
  35 + <li id='nav-proposal-group'>
  36 + <a href="#/programas">Programas</a>
  37 + </li>
34 </ul> 38 </ul>
35 </nav> 39 </nav>
36 40
@@ -38,12 +42,12 @@ @@ -38,12 +42,12 @@
38 <div id="proposal-categories-container"> 42 <div id="proposal-categories-container">
39 {{#each article.categories}} 43 {{#each article.categories}}
40 <li id='proposal-category-{{slug}}' class="proposal-category" data-category="{{slug}}"> 44 <li id='proposal-category-{{slug}}' class="proposal-category" data-category="{{slug}}">
41 - {{#link name id}}{{/link}} 45 + <a href="#/temas/{{slug}}/{{id}}" class="proposal-link" data-target="proposal-item-{{id}}">{{name}}</a>
42 <div class="arrow-box" style="display: none"></div> 46 <div class="arrow-box" style="display: none"></div>
43 </li> 47 </li>
44 {{/each}} 48 {{/each}}
45 {{#each article.categories}} 49 {{#each article.categories}}
46 - <div id='proposal-item-{{id}}' class="proposal-category-items proposal-category-items-{{slug}} hide"> 50 + <div id='proposal-item-{{id}}' class="proposal-category-items proposal-category-items-{{slug}} hide" data-category="{{slug}}">
47 <div class="header"> 51 <div class="header">
48 <div class="name">{{name}}</div> 52 <div class="name">{{name}}</div>
49 <div class="description"></div> 53 <div class="description"></div>
@@ -77,7 +81,7 @@ @@ -77,7 +81,7 @@
77 <ul class="select"> 81 <ul class="select">
78 {{#each categories}} 82 {{#each categories}}
79 <li class='category proposal-category' data-category="{{slug}}"> 83 <li class='category proposal-category' data-category="{{slug}}">
80 - {{#link name id}}{{/link}} 84 + <a href="#/temas/{{slug}}/{{id}}" class="proposal-link" data-target="proposal-item-{{id}}">{{name}}</a>
81 {{#select_proposal ../../article.children slug ../id}}{{/select_proposal}} 85 {{#select_proposal ../../article.children slug ../id}}{{/select_proposal}}
82 </li> 86 </li>
83 {{/each}} 87 {{/each}}
@@ -89,13 +93,18 @@ @@ -89,13 +93,18 @@
89 </div> 93 </div>
90 <div class='title'>{{title}}</div> 94 <div class='title'>{{title}}</div>
91 <div class='abstract'>{{{abstract}}}</div> 95 <div class='abstract'>{{{abstract}}}</div>
92 - <div class='show_body'><a href='#'><span>Conheça o Programa</span></a></div> 96 + <div class='show_body'>
  97 + <a href='#/programas/{{id}}/sobre-o-programa'><span>Conheça o Programa</span></a>
  98 + </div>
93 </div> 99 </div>
94 100
95 <div class='body proposal-detail-base hide'> 101 <div class='body proposal-detail-base hide'>
96 {{{body}}} 102 {{{body}}}
97 - <div class='go-to-proposal-button'><a href='#proposal-item-{{id}}'>  
98 - <div class='fa fa-reply'> </div>Agora contribua para a melhoria desse programa</a> 103 + <div class='go-to-proposal-button'>
  104 + <a href="#/programas/{{id}}" data-target='proposal-item-{{id}}'>
  105 + <span class='fa fa-reply'></span>
  106 + Agora contribua para a melhoria desse programa
  107 + </a>
99 </div> 108 </div>
100 109
101 </div> 110 </div>
@@ -173,7 +182,6 @@ @@ -173,7 +182,6 @@
173 </div> 182 </div>
174 </div> 183 </div>
175 </div> 184 </div>
176 - <div class="clearfix"></div>  
177 </div> 185 </div>
178 {{/each}} 186 {{/each}}
179 </script> 187 </script>
js/handlebars-helpers.js
@@ -2,7 +2,8 @@ Handlebars.registerHelper(&#39;link&#39;, function(text, url) { @@ -2,7 +2,8 @@ Handlebars.registerHelper(&#39;link&#39;, function(text, url) {
2 text = Handlebars.Utils.escapeExpression(text); 2 text = Handlebars.Utils.escapeExpression(text);
3 url = Handlebars.Utils.escapeExpression(url); 3 url = Handlebars.Utils.escapeExpression(url);
4 4
5 - var result = '<a id="#' + url + '" href="#proposal-item-' + url + '" class="proposal-link">' + text + '</a>'; 5 + // Exemplo: <a href="#/programas/{{id}}" class="proposal-link" data-target="">{{name}}</a>
  6 + var result = '<a href="#/programas/' + url + '" data-target="proposal-item-' + url + '" class="proposal-link">' + text + '</a>';
6 7
7 return new Handlebars.SafeString(result); 8 return new Handlebars.SafeString(result);
8 }); 9 });
@@ -40,52 +40,55 @@ $.getJSON(noosferoAPI) @@ -40,52 +40,55 @@ $.getJSON(noosferoAPI)
40 $('.login-container').html(loginTemplate()); 40 $('.login-container').html(loginTemplate());
41 $('.countdown').maxlength({text: '%left caracteres restantes'}); 41 $('.countdown').maxlength({text: '%left caracteres restantes'});
42 42
43 - url = $(location).attr('href').split('#').pop();  
44 - if(url.match(/proposal-item-[0-9]+/)){  
45 - display_proposal(url);  
46 - } 43 + navigateTo(window.location.hash);
  44 +
47 //Actions for links 45 //Actions for links
48 $( '#nav-proposal-categories a' ).click(function(event){ 46 $( '#nav-proposal-categories a' ).click(function(event){
49 - //Display the category tab  
50 - $('#proposal-group').hide();  
51 - $('#proposal-categories').show();  
52 - $('#nav-proposal-categories a').addClass('active');  
53 - $('#nav-proposal-group a').removeClass('active');  
54 - $('.proposal-category-items').hide();  
55 - $('.proposal-category .arrow-box').hide();  
56 - $('.proposal-detail').hide();  
57 event.preventDefault(); 47 event.preventDefault();
  48 +
  49 + var $link = $(this);
  50 +
  51 + // Update URL
  52 + updateHash($link.attr('href'));
  53 +
  54 + // Display the Category tab
  55 + display_category_tab();
58 }); 56 });
  57 +
59 $( '#nav-proposal-group a' ).click(function(event){ 58 $( '#nav-proposal-group a' ).click(function(event){
60 - //Display the Topics or Discussions tab  
61 - $('#proposal-categories').hide();  
62 - $('#proposal-group').show();  
63 - $('#nav-proposal-group a').addClass('active');  
64 - $('#nav-proposal-categories a').removeClass('active');  
65 - $(".proposal-item p").dotdotdot();  
66 event.preventDefault(); 59 event.preventDefault();
  60 +
  61 + var $link = $(this);
  62 +
  63 + // Update URL
  64 + updateHash($link.attr('href'));
  65 +
  66 + //Display the Proposals tab
  67 + display_proposals_tab();
67 }); 68 });
  69 +
68 $( '.proposal-item a' ).click(function(event){ 70 $( '.proposal-item a' ).click(function(event){
69 - var item = this.href.split('#').pop(); 71 + var $link = $(this);
  72 + var item = $link.data('target');
  73 +
  74 + // Update URL
  75 + updateHash($link.attr('href'));
  76 +
70 display_proposal(item); 77 display_proposal(item);
71 }); 78 });
  79 +
72 $( '.proposal-category a' ).click(function(event){ 80 $( '.proposal-category a' ).click(function(event){
73 - var item = this.href.split('#').pop();  
74 - if($('#' + item).hasClass('proposal-category-items')){  
75 - //Display Topics or Discussion by category  
76 - $('nav').show();  
77 - $('#content').show();  
78 - $('#proposal-categories').show();  
79 - $('.proposal-category-items').hide();  
80 - $('.proposal-detail').hide();  
81 - $('#' + item).show();  
82 - $(".proposal-item p").dotdotdot();  
83 - $('.proposal-category .arrow-box').hide();  
84 - $(this).parent('.proposal-category').data('category');  
85 - $('#proposal-category-'+$(this).parent('.proposal-category').data('category')).find('.arrow-box').show();  
86 - }  
87 event.preventDefault(); 81 event.preventDefault();
  82 +
  83 + var $link = $(this);
  84 + var item = $link.data('target');
  85 +
  86 + // Update URL
  87 + updateHash($link.attr('href'));
  88 +
  89 + display_proposal_by_category(item);
88 }); 90 });
  91 +
89 $( '.send-button a' ).click(function(event){ 92 $( '.send-button a' ).click(function(event){
90 //display form to send proposal (or login form for non-logged users) 93 //display form to send proposal (or login form for non-logged users)
91 loginButton = $(this).parents('.send-button'); 94 loginButton = $(this).parents('.send-button');
@@ -98,11 +101,25 @@ $.getJSON(noosferoAPI) @@ -98,11 +101,25 @@ $.getJSON(noosferoAPI)
98 $('#proposal-result').toggleClass('contrast'); 101 $('#proposal-result').toggleClass('contrast');
99 }); 102 });
100 $( '.show_body a' ).click(function(event){ 103 $( '.show_body a' ).click(function(event){
101 - display_proposal_detail(); 104 + event.preventDefault();
  105 +
  106 + var $link = $(this);
  107 + var item = $link.data('target');
  108 +
  109 + // Update URL
  110 + updateHash($link.attr('href'));
102 }); 111 });
  112 +
103 $( '.go-to-proposal-button a' ).click(function(event){ 113 $( '.go-to-proposal-button a' ).click(function(event){
104 - display_proposal(this.href.split('#').pop()); 114 + event.preventDefault();
  115 +
  116 + var $link = $(this);
  117 + var item = $link.data('target');
  118 +
  119 + // Update URL
  120 + updateHash($link.attr('href'));
105 }); 121 });
  122 +
106 $( '.proposal-selection' ).change(function(event){ 123 $( '.proposal-selection' ).change(function(event){
107 display_proposal('proposal-item-' + this.value); 124 display_proposal('proposal-item-' + this.value);
108 }); 125 });
@@ -111,6 +128,7 @@ $.getJSON(noosferoAPI) @@ -111,6 +128,7 @@ $.getJSON(noosferoAPI)
111 $('#proposal-group li a').each(function(){ 128 $('#proposal-group li a').each(function(){
112 availableTags.push({ label: $(this).text(), value: $(this).attr('href')}); 129 availableTags.push({ label: $(this).text(), value: $(this).attr('href')});
113 }); 130 });
  131 +
114 $( "#search-input" ).autocomplete({ 132 $( "#search-input" ).autocomplete({
115 source: availableTags, 133 source: availableTags,
116 select: function( event, ui ) { display_proposal(ui.item['value' ].replace('#','')); }, 134 select: function( event, ui ) { display_proposal(ui.item['value' ].replace('#','')); },
@@ -143,7 +161,7 @@ $.getJSON(noosferoAPI) @@ -143,7 +161,7 @@ $.getJSON(noosferoAPI)
143 .fail(function( jqxhr, textStatus, error ) { 161 .fail(function( jqxhr, textStatus, error ) {
144 var err = textStatus + ", " + error; 162 var err = textStatus + ", " + error;
145 console.log( "Request Failed: " + err ); 163 console.log( "Request Failed: " + err );
146 - }); 164 + });
147 165
148 function loadRandomProposal(topic_id, private_token) { 166 function loadRandomProposal(topic_id, private_token) {
149 $(".no-proposals").hide(); 167 $(".no-proposals").hide();
@@ -160,7 +178,7 @@ function loadRandomProposal(topic_id, private_token) { @@ -160,7 +178,7 @@ function loadRandomProposal(topic_id, private_token) {
160 178
161 var article = data.articles[0]; 179 var article = data.articles[0];
162 $('.random-proposal').html(supportProposalTemplate(article)); 180 $('.random-proposal').html(supportProposalTemplate(article));
163 - $(".abstract").dotdotdot(); 181 + // $(".abstract").dotdotdot();
164 $(document.body).off('click', '.vote-actions .skip'); 182 $(document.body).off('click', '.vote-actions .skip');
165 $(document.body).on('click', '.vote-actions .skip', function(e) { 183 $(document.body).on('click', '.vote-actions .skip', function(e) {
166 loadRandomProposal(topic_id, private_token); 184 loadRandomProposal(topic_id, private_token);
@@ -181,10 +199,6 @@ function loadRandomProposal(topic_id, private_token) { @@ -181,10 +199,6 @@ function loadRandomProposal(topic_id, private_token) {
181 e.preventDefault(); 199 e.preventDefault();
182 }); 200 });
183 201
184 - $('.results-container').hide();  
185 - $('.experience-proposal-container').show();  
186 - $('.talk-proposal-container').show();  
187 -  
188 $(document.body).off('click', '.vote-result'); 202 $(document.body).off('click', '.vote-result');
189 $(document.body).on('click', '.vote-result', function(e) { 203 $(document.body).on('click', '.vote-result', function(e) {
190 $('.results-container').toggle(); 204 $('.results-container').toggle();
@@ -266,6 +280,24 @@ function guid() { @@ -266,6 +280,24 @@ function guid() {
266 s4() + '-' + s4() + s4() + s4(); 280 s4() + '-' + s4() + s4() + s4();
267 } 281 }
268 282
  283 +function display_category_tab(){
  284 + $('#proposal-group').hide();
  285 + $('#proposal-categories').show();
  286 + $('#nav-proposal-categories a').addClass('active');
  287 + $('#nav-proposal-group a').removeClass('active');
  288 + $('.proposal-category-items').hide();
  289 + $('.proposal-category .arrow-box').hide();
  290 + $('.proposal-detail').hide();
  291 +}
  292 +
  293 +function display_proposals_tab(){
  294 + $('#proposal-categories').hide();
  295 + $('#proposal-group').show();
  296 + $('#nav-proposal-group a').addClass('active');
  297 + $('#nav-proposal-categories a').removeClass('active');
  298 + $(".proposal-item p").dotdotdot();
  299 +}
  300 +
269 function display_proposal(proposal_id){ 301 function display_proposal(proposal_id){
270 $('#proposal-categories').hide(); 302 $('#proposal-categories').hide();
271 $('#proposal-group').hide(); 303 $('#proposal-group').hide();
@@ -302,6 +334,87 @@ function display_proposal_detail(){ @@ -302,6 +334,87 @@ function display_proposal_detail(){
302 $('.talk-proposal-container').hide(); 334 $('.talk-proposal-container').hide();
303 335
304 $('.body').show(); 336 $('.body').show();
305 - event.preventDefault(); 337 +}
  338 +
  339 +function display_proposal_by_category(item){
  340 + var $item = $('#' + item);
  341 +
  342 + if($item.hasClass('proposal-category-items')){
  343 + //Display Topics or Discussion by category
  344 + $('nav').show();
  345 + $('#content').show();
  346 + $('#proposal-categories').show();
  347 + $('.proposal-category-items').hide();
  348 + $('.proposal-detail').hide();
  349 + $item.show();
  350 + $(".proposal-item p").dotdotdot();
  351 + $('.proposal-category .arrow-box').hide();
  352 + var categorySlug = $item.data('category');
  353 + $('#proposal-category-' + categorySlug).find('.arrow-box').show();
  354 + }
  355 +}
  356 +
  357 +function updateHash(hash){
  358 + var id = hash.replace(/^.*#/, '');
  359 + var elem = document.getElementById(id);
  360 +
  361 + if ( !elem ) {
  362 + window.location.hash = hash;
  363 + return;
  364 + }
  365 +
  366 + elem.id = id+'-tmp';
  367 + window.location.hash = hash;
  368 + elem.id = id;
  369 +}
  370 +
  371 +function locationHashChanged(){
  372 + var hash = location.hash;
  373 + navigateTo(hash);
  374 +}
  375 +
  376 +function navigateTo(hash){
  377 + var regexProposals = /#\/programas/;
  378 + var regexCategory = /#\/temas/;
  379 + var m;
  380 + var parts = hash.split('/');
306 381
  382 + if( (m = regexProposals.exec(hash)) !== null ){
  383 + var proposalId = parts[2];
  384 + navigateToProposal(proposalId);
  385 + } else if( (m = regexCategory.exec(hash)) !== null ){
  386 + var categoryId = parts[3];
  387 + navigateToCategory(categoryId);
  388 + } else {
  389 + console.log('route not handled', hash);
  390 + }
307 } 391 }
  392 +
  393 +function navigateToProposal(proposalId){
  394 + if(proposalId === undefined){
  395 + display_proposals_tab();
  396 + }else{
  397 + display_proposal('proposal-item-' + proposalId);
  398 +
  399 + // show sub-page
  400 + var regexSubpages = /sobre-o-programa$/;
  401 + var m;
  402 + if((m = regexSubpages.exec(window.location.hash)) !== null ){
  403 + display_proposal_detail();
  404 + }
  405 + }
  406 +}
  407 +
  408 +function navigateToCategory(categoryId){
  409 + if(categoryId === undefined){
  410 + display_category_tab();
  411 + }else{
  412 + display_proposal_by_category('proposal-item-' + categoryId)
  413 + }
  414 +}
  415 +
  416 +if("onhashchange" in window){
  417 + window.onhashchange = locationHashChanged;
  418 +}else{
  419 + console.log('The browser not supports the hashchange event!');
  420 +}
308 \ No newline at end of file 421 \ No newline at end of file
sass/_proposal_group.scss
@@ -11,8 +11,7 @@ @@ -11,8 +11,7 @@
11 11
12 #search-input-container, label[for=search] { 12 #search-input-container, label[for=search] {
13 width: 49%; 13 width: 49%;
14 - display: inline-block;  
15 - height: 80px; 14 + height: 80px;
16 vertical-align: middle; 15 vertical-align: middle;
17 overflow: hidden; 16 overflow: hidden;
18 } 17 }