How to create a site without reloading every click on a link?

112

I want to develop a site that runs around the same file, but I'm not sure how to look for study material for that.

So:

Normal site-> I'm on the Index.php page. When I click on the "Portfolio" menu, for example, it goes and loads the file Porfolio.php.

The site I want to do-> I'm on the Index.php page. When I click on the "Portfolio" menu, the site does an animation (fade, side-scroll, etc.) and shows the contents of the Portfolio, without having to load another file.

Can anyone give me a light? I have worked with one-page sites, but they are on the One Page Scroll Website template.

I think I need to work with AJAX, but I'm not sure yet.

    
asked by anonymous 20.02.2014 / 05:48

10 answers

96

Conceptually, you have three options:

# 1 - Single file without AJAX

In this case you can have all the content on the same page. Non-show content must be hidden with, for example, display: none;

<div id="menu">
    <div id="a">A</div>
    <div id="b">B</div>
    <div id="c">C</div>
</div>
<div id="conteudo">
    <div class="a visivel">Conteudo A</div>
    <div class="b">Conteudo B</div>
    <div class="c">Conteudo C</div>
</div>

CSS

#conteudo > div{
    display: none;

}
#conteudo > div.visivel{
    display: block;
}

Example

# 2 - Single file with AJAX with everything visible and with scroll

In this case you can have a menu where clicking triggers a scroll. For this it needs to have anchors to be able to shoot a scroll there. You can also trigger the scroll by looking for the position / size of the elements but it is less practical

<div id="menu">
    <div><a href="#a">A</a></div>
    <div><a href="#b">B</a></div>
    <div><a href="#c">C</a></div>
</div>
<div id="conteudo">
    <div class="a visivel"><a name="a"></a>Conteudo A</div>
    <div class="b"><a name="b"></a>Conteudo B</div>
    <div class="c"><a name="c"></a>Conteudo C</div>
</div>

Example

# 3 - Multiple files with AJAX

In this case you have different files on the server side and will fetch them via AJAX. In the AJAX response function, load this HTML into the page art you want. Deleting the initial content of this element / part of the page.

HTML

<div id="menu">
    <div id="a">A</div>
    <div id="b">B</div>
    <div id="c">C</div>
</div>
<div id="conteudo"></div>

jQuery

$('#menu > div').on('click', function (e) {
    e.preventDefault(); // para impedir o link de ser seguido
    url = '/shmD9/show';    // usado para o meu exemplo
    var aClasse = this.id;
    $.ajax({
        url: url,
        // aqui um parametro "data: variável," é necessário
        success: function (returnhtml) {  // função corrida no sucesso do ajax
            var tempText = (returnhtml.split('<body>'))[1].split('</body>')[0];  // só util no meu exemplo
            var divEnscolhido = $('<div></div>').append(tempText).find('.' + aClasse); // só util 
            $('#conteudo').html(divEnscolhido); // esta é a parte importante, onde o conteudo da div é substituído pelo novo
        }
    });
});

Example

Considerations to take into account:

Both methods 1 and 3 are un-friendly SEO. This means that for example Google when trying to index content of the page will have problems. If your page is not well indexed by Google then you do not have content to show on searches and will have less visibility / visits. In the case of Google it indexes hidden content, but it is not guaranteed that others will. (And in case of option 3 is even worse)

    
20.02.2014 / 09:11
50

I use AngularJS to make websites on one page, it's much easier and simpler to use than ajax and other paraphernalia see this one

Step by step of a single-page site

Before you begin, all of the code below is working: link

To have page redirection control you need to follow a few steps sooner.

Referencing the AngularJS routing libraries

Refer to the ngRoute module in your html:

<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"</script><scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular-route.min.js"></script>
</head>

Modularizing Your App

It is only possible to control page routing with a modularized application, create your module referencing angular-route as follows:

var app = angular.module("app", ["ngRoute"]);

And in the <html> tag add:

<html ng-app='app'>

The variable app is global and you can call services , factories , and configuration methods.

Let's add factory of tasks just to ensure controllers are using the same tasks list. Therefore, the two controllers, one for the view of Detalhes and another for Listagem :

/*1*/   app.factory("TaskFactory",function(){  
/*2*/     var tasklist =  [              
/*3*/        {name:"terminar meu app",id:0}, 
/*4*/        {name:"comprar presente para minha irmã",id:1}
/*5*/        ]; 
/*6*/          return{
/*7*/            get : function(){
/*8*/            return tasklist;
/*9*/          }
/*10*/       };
/*11*/   });
/*12*/    app.controller('TaskListCtrl', function ($scope,TaskFactory) {
/*13*/      (function(){$scope.tasks=TaskFactory.get();})();
/*14*/    });
/*15*/    app.controller('TaskDetailCtrl', function ($scope,TaskFactory,$routeParams) {
/*16*/      (function(){$scope.task=TaskFactory.get()[$routeParams.taskId];})();
/*17*/    });

Line Details:

Line 1 - Creating factory

Line 3 - Let's use id of the task to call it view of listing for details

Line 6 - Returning a method to call the task list from factory

Line 12 - Creating the controller TaksListCtrl that is receiving by argument the $scope and TaskFactory which is the factory. It must be the same name called in the argument and registered in app.factory()

Line 13 - Populating $scope.tasks with the list of tasks that returns TaskFactory.Get();

Line 15 - Creating controller TaskDetailCtrl which will be responsible for displaying the selected task in the other view . The difference is that I am now getting by argument the $routeParams of the module ngRoute which is responsible for keeping the data that you pass in URL

Line 16 - Again I'm taking tasks from TaskFactory but this time I'm filtering for those that contains the id = $routeParams.taskId (we'll see why this one) so it will only bring one task.

You could do this too if you prefer:

//esta forma
var tasks = TaskFactory.get();
var id = $routeParams.taskId;
$scope.task = tasks[id];

//é a maneira simplificada desta
$scope.task=TaskFactory.get()[$routeParams.taskId];

Configure routes in% with%

Space is required in the html to allow AngularJS to manipulate your DOM

<body>
  <div >
    <ng-view></ng-view>
  </div>
 </body>

Only use the app.config() directive in some ng-view tag and you're done, you do not need to reference controllers or anything, this will be registered with <div> as follows:

/*1 */   app.config(function($routeProvider) {
/*2 */       $routeProvider.when('/',{
/*3 */           template: 'Lista de Tasks:'+
/*4 */             '<div >'+
/*5 */           '<div ng-repeat="task in tasks">'+
/*6 */         '{{task.id}} - {{task.name}}'+
/*7 */           '<div><a ng-href="#/{{task.id}}">detalhes</a>'+
/*8 */       '</div></div>'+
/*9 */     '</div>',
/*10*/            controller: "TaskListCtrl"
/*11*/          }).
/*12*/        when('/:taskId',{
/*13*/            template: 'Detalhes da Task {{task.id}}:'+
/*14*/              '<h4>Nome: {{task.name}}</h4>'+ 
/*15*/              '</div>'+'<a ng-href="#/"> Voltar</a>',
/*16*/            controller: "TaskDetailCtrl"
/*17*/          }
/*18*/        ).otherwise({redirect:'/'});
/*19*/    });

What the above code does is:

Line 1 - invokes method app.config() of module passing config that receives function

Line 2 - In $routeProvader you have the methods $routeProvader and when() , each receives an object with the routing properties, for example:

when("/url que vc deseja",{
  template: "aqui vai o html que será renderizado dentro de ng-view"
  controller: "aqui o nome do controller correspondente àquela url"
});

otherwise({redirect:"/"}) //quer dizer que se nao for nenhuma das url registradas,
// redirecionara para a principal

In the first otherwise() , I'm going to pass that if it does not have parameters, it will call that template using the "TaskListCtrl". If the template is too large, it is recommended to save it to another file and call it when() instead of just {templateUrl:'exemplo.html'}

On line 7 I'm simply creating a link to template , angle will replace #/{{task.id}} with task id.

IMPORTANT: In line 12, taskId is receiving when , sign \:taskId indicates that it is a parameter, this is necessary to say to : that is called in $routeParams , that it will have the controller property, see:

Inaddition,youarepassingtaskIdandtyingtocontrollertemplate

Summary

Ready,thesestepsarerequiredtodoasimpleroutingcontrolusingAngularJSsummarizing:

  • Referencingangular.jsandangular-route.js
  • CreateamodulefortheapplicationbyreferencingTaskDetailCtrl
  • Add%with%
  • Createthecontrollersandfactories/serivces
  • Addtheargument['ngRoute']tothecontrollerthatusesit.
  • Callng-viewinhtmllikethis:<htmlng-app='nomeDoModulo'>
  • Invoking$routeParamstologroutes(including<divng-view></div>onlyworksiftheroutedrouteisregisteredhere.
  • Calltheapp.config(function($routeProvider){...})methodforeachrouteinyourapplicationbypassingthecorrectparameters
  • Distributetags$location
  • Use$routeProvider.when()asneeded.
  • Apprunninghere: link

        
    11.04.2014 / 20:12
    25

    From my point of view, all the answers are correct, but no one has remembered another way to do this, using AngularJS and the ngView feature you can do this in a practical and fast way is the angle itself already supports transition animations .

    Example on Plunker

        
    25.02.2014 / 12:35
    18

    This can be done in several ways. You can use a script to send ajax requests by clicking links to the same domain as your site:

    (function() {
        var content = document.getElementById("div-id"), // Substitua "div-id" pelo ID da div do conteúdo do seu site
            links = document.getElementsByTagName("a");
    
        function listener(e) {
            loadPage(this);
            e.preventDefault();
            e.stopPropagation();
        }
    
        function loadPage(target) {
            var xmlhttp,
                url = target.href;
            if(target.search) {
                url += "&ajax=1";
            } else {
                url += "?ajax=1";
            }
            if(typeof window.XMLHttpRequest === "undefined") {
                try {
                    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.6.0");
                } catch(e) { try {
                    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP.3.0");
                } catch(e) { try {
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch(e) {
                    return;
                }}}
            } else {
                xmlhttp = new XMLHttpRequest();
            }
            xmlhttp.onreadystatechange = function() {
                if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    // Animação...
                    try {
                        var response = JSON.parse(xmlhttp.responseText);
                        window.history.pushState({
                            url: url
                        }, response.title || document.title, url);
                        document.title = response.title;
                        content.innerHTML = content;
                    } catch(e) { }
                }
            };
            xmlhttp.open("GET", url, false);
            xmlhttp.send();
        }
    
        for(var i = 0; i < links.length; ++i) {
            if(links[i].hostname === window.location.hostname &&
               links[i].protocol === window.location.protocol) {
                if(links[i].addEventListener) {
                    links[i].addEventListener("click", listener);
                } else if(links[i].attachEvent) {
                    links[i].attachEvent("onclick", listener);
                }
            }
        }
    })();
    

    This script adds the variable "json" to the url query string, which will be used to determine if the script will generate a json object or the entire page layout:

    <?php
    // Gerar o conteúdo e título
    if(isset($_GET['json'])) {
        header("Content-Type: application/json");
        echo json_encode(array(
            'title'   => $titulo_da_pagina,
            'content' => $conteúdo_da_pagina
        ));
    } else {
        // Exibir o layout inteiro
    }
    

    This way the site works even without javascript.

        
    20.02.2014 / 10:07
    12

    You could use the "load" function of jquery and update a particular element of the page, for example, let's assume that every time you click on elements with the "change-content" class, it uses "href" to fetch the new page, and update the "#content" would be something like:

    <nav>
         <a href="contato.html" class="change-content">Contato</a>
         <a href="empresa.html" class="change-content">Empresa</a>
    </nav>
    <section id="content"></section>
    
    <script>
        $(document).ready(function() {
            $('.change-content').click(function() {
                $("#content").load($(this).attr('href'));
                return false;
            });    
        });
    </script>
    
        
    14.08.2014 / 13:42
    11

    Using Ajax is easy. Just follow my example below:

    <head>
    <title>Site</title>
    </head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script><body><divid="menu"><a data="porfolio.php" id="porfolio" onclick="getPage(this.id);" style="cursor:hand;text-
    
    decoration:underline;">Porfolio</a></div>
    
    <script>function getPage(a){ 
        $.get(document.getElementById(a).getAttribute('data'), function(data){ paginas = data; });
    }</script>
    
    <div id="paginas">Página Inicial</div>
    
    </body>
    

    Note: Remember to put the CSS and Javascript that you instantiate always on the main page. Here is the beginning, just format the CSS and create the links, Apply on the site that is doing the technology. For the home page, just place the content on a page. Ex: initial.php

    In this case, I would put the line inside the script:

    $.get('inicial.php', function(data){ paginas = data; });
    
        
    19.08.2015 / 19:56
    8

    It will be necessary to use AJAX, basically you will have a page that will show the contents of the other files like sobre.php, contato.php, portfolio.php through the load () of jquery or open ('GET'). javascript and callback you can trigger the effect you want.

    Look at this script in jQuery ( JSFiddle )

    # can also help you

    $(document).ready(function() {
        var paginaXXX = "paginaXXX.php";
        // On click faz o load
        $('input[type="button"]').click(function(){
            // Oculta a pagina actual
            $('.conteudoActual').hide();
            // Mostra a div carregando
            $('.carregando').fadeIn();
            // Lê o conteudo e quando o conteúdo for lido 
            // apresenta a pagina
            $('.conteudo').load(paginaXXX, function() {
                // Oculta o carregando
                $('.carregando').hide();
                // Mostra a página requisitada
                $('.conteudo').fadeIn();
            });
        });
    });
    
        
    20.02.2014 / 09:19
    8

    ** This response has been rewritten for better understanding. The question itself is to exchange information or even make posts in PHP without using forms (which usually reload the pages or direct them to other places)

    As far as I know there is no other way but Ajax, which can be done in 3 ways that I know, but I will demonstrate the $ .load method:
    LOAD
    This method works best for the question that the user has proposed. I will detail a little more by applying to a model. Let's say that on the server you have a folder of a web project called "Project". Inside the project folder we have the "index.php", "pagina1.php", "pagina2.php" and so on ... Home INDEX.PHP

    //não vou colocar o cabeçalho completo, lembro que você deve indicar o jquery no seu cabeçalho
    <head>
        <script>
            $(document).ready(function(){
                /
                $("#content").load("pagina1.php"); //aqui ele carrega a primeira página no content para ele não ficar em branco
                $(".menu a").click(function(){ //quando o usuario clicar em qualquer opção do menu
                    var pagina = $(this).attr("id"); //obtém o id do item clicado que é equivalent ao nome da página
                    var param = $(this).attr("class"); //obtém a classe, a idéia é passar a classe para o PHP como um parâmentro
                    $("#content").load(pagina+".php", {"param":param}, function(){
                        alert("Ok, a página "+pagina+" foi atualizada com sucesso!"); 
                        //Retorno para saber que a atualização ou troca ocorreu, isso não é tão necessário
                        //Mas se você precisa executar outra funcção com o resultado do load é bom utilizar isso
                    });
                });
            });
        </script>
    </head>
    <body>
        <div class="menu">
            <a href="#" class="item1" id="pagina1">Pagina1</a>
            <a href="#" class="item2" id="pagina2">Pagina2</a>
            ...
        </div>
        <div id="content">
            //os dados serão carregados aqui conforme seleção
        </div>
    </body>
    

    PAG1.PHP

    <table>
        <thead>
            <th>Nome</th>
            <th>Idade</th>
            <th>Sexo</th>
        </thead>
        <tbody>
        <?php
        //inclua sua conexão com o banco
        include "conexão.php";
        $param = $_POST['param']; //recebendo o paramento postado
        $sql = "select nome, idade, sexo from usuarios where idade = '$param'"; // um exemplo de consulta utilizando o parametro postado
        $result = $conn->query($sql);
        while($row = $result->fetch_assoc()){ 
            echo    "<tr> //escrevendo as linhas com os dados
                        <td>".$row['nome']."</td>
                        <td>".$row['idade']."</td>
                        <td>".$row['sexo']."</td>
                    </tr>";
        }
        ?>
        </tbody>
    </table>
    

    In summary when the user clicks on page1 an updated table should appear in the content. From this example you can imagine what you can do using load.

        
    08.09.2016 / 17:26
    6

    You can use a switch. Let's say you're on the index.php page and want to go to the "A" page. The link should be:

    <a href="?pag=A">Ir para a Página "A"</a>
    

    Now on the page index.php should contain the receipt of the GET as follows:

    $pag = isset($_GET['pag'])?$_GET['pag']:"";
    

    That is, if the variable $ _GET ["pag"] was set in the link, then the variable is what is in the link, otherwise the variable is null.

    Next you have to make the switches. Use as follows:

    switch($pag){   // Inicia o switch que vai carregar uma informação diferente a cada case
    
      case "A":
    
       echo "aqui vai o conteudo da página "";
    
      break;  // Indica que o case "A" terminou
    
      case "B":
    
       echo "aqui vai o conteudo da página "";
    
      break;  // Indica que o case "B" terminou
    
      case "C":
    
       echo "aqui vai o conteudo da página "";
    
      break;  // Indica que o case "C" terminou
    
    } // Encerra o switch
    
        
    24.10.2017 / 20:06
    0

    I've already asked a question like this.

    Look at this link

    This example uses the .load function of jQuery to load the content.

      

    DIFFERENT FROM THE OTHER EXAMPLES CITED, YOU WILL HAVE NO PROBLEMS WITH SEO

    SEO and Easy solution, because with it you will have no problem / em> and your pages will be indexed on Google normally.

    When browsing, note that Title <title> , URL , and content <body> are changed.

    It will work just like any other common site, but in AJAX .

    EXAMPLES

      

    I made some fixes with the help of the user @Jader | You can see them below:

    EXAMPLE COM CORREÇÕES

    Now all pages that are directly accessed will have the same effect as the home page.

    SEE: BEFORE ||| AFTER

    DOWNLOAD

    I've made some edits (improvements) and you can download it here:

    DOWNLOAD (Site in Ajax.zip) (3KB)

    | ill | lIi | Note: Only works if it is hosted or localhost.

      

    I also had the doubt of how to make it work. No doubt this is the best solution.

        
    15.08.2014 / 04:23