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

Asked

Viewed 13,997 times

123

I’m looking to develop a site that runs all in the same file, but I’m not sure how to look for study material for this.

Thus:

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

Site I want to do->am on the page Index.php. When I click on the "Portfolio" menu, the site makes an animation (fade, side-scroll, etc.) and shows the contents of the Portfolio, without the need to upload another file.

Can someone give me a light? I’ve worked with sites made in one page, but are in the model One Page Scroll Website.

I believe I need to work with AJAX, but I’m not sure yet.

  • 3

    Related/duplicate: http://answall.com/questions/4450/navegaca-sem-refresh

  • 2

    use SPA frameworks such as: Angularjs (recommend this one), Backbone, Ember, among others

  • 1

    You can use the Extjs Framework Extjs!

  • 1

    This is very common in hotsites, look at this example

  • you can use load() in jquery [http://api.jquery.com/load/]

9 answers

103


In a conceptual way, there are three options:

#1 - Single file without AJAX

In this case you can have all the content on the same page. The content that is not to show 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 without AJAX with all visible and scroll

In this case you can have a menu where clicking fires a scroll. For this you need to have anchors to be able to fire a scroll there. You can also fire the scroll 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 fetch them via AJAX. In the AJAX response function you load this HTML into the art of the desired page. 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 be taken into account:

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

  • 5

    In cases where there are problems with the google robot (#1 and #3), a solution would be to identify that the visitor is the google robot and then render all visible content (like case #2).

52

I use Angularjs to make websites on a single page, it is much easier and simple to use than ajax and other paraphernalia see only this

Step by step from single page site

Before you start, all the code below is working on: http://jsbin.com/roqil/edit

To have control of redirecting pages you need to follow a few steps before.

Reference the Angularjs routing libraries

Reference the module ngRoute in your html:

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

Modularize your App

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

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

And on the tag <html> add :

<html ng-app='app'>

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

Let’s add a factory of tasks only to ensure that controllers are using the same tasks list. So, the two controllers, one for the view of Detalhes and another to 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*/    });

Details of the Lines:

Line 1 - Creating the factory

Line 3 - We will use the id of the task to call it view listing for details

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

Line 12 - Creating the controller TaksListCtrl which is receiving by argument the $scope and TaskFactory which is Factory. It has to be the same name called in the argument and recorded in the app.factory()

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

Line 15 - Creating the controller TaskDetailCtrl who will be responsible for presenting the task selected in the other view. The difference is that now I’m getting by argument the $routeParams module ngRoute who is responsible for keeping the data you pass on URL

Line 16 - Again I’m picking up tasks from TaskFactory but this time I’m filtering for those that contain the id = $routeParams.taskId (we will see ahead why this) then it will bring only one task.

I could do that 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 the routes in app.config()

You need to reserve a space in html to allow Angularjs to manipulate your DOM

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

Just use the directive ng-view at some tag <div> You don’t need to reference controllers or anything like that, it will be recorded in app.config() next:

/*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 - invoke method config of the module passing a function who receives the $routeProvader

Line 2 - No $routeProvader you have the methods when() and otherwise() , 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 when() I am passing that if you do not have parameters, you will call that template using "Tasklistctrl". If the template is too large, it is recommended to store it in another file and call it so {templateUrl:'exemplo.html'} alas instead of just template

On line 7 I am simply creating a link to #/{{task.id}}, the angular will replace the taskId by the id of the task.

IMPORTANT: On line 12 o when are receiving \:taskId, the sign : indicates that it is a parameter, this is necessary to say to the $routeParams which is called in the controller, that he will own the property taskId, see:

inserir a descrição da imagem aqui

In addition, is passing the template and tying to the controller TaskDetailCtrl

Summary

Ready, these steps are necessary to make a simple routing control using Angularjs summing up:

  1. Referencing angular.js and angular-route.js
  2. Create a module for the application referencing ['ngRoute']
  3. Add <html ng-app='nomeDoModulo'>
  4. Create controllers and Factories/serivces
  5. Add argument $routeParams in the controller using this.
  6. Call ng-view in html like this: <div ng-view></div>
  7. Invoke app.config(function($routeProvider){...}) to register routes (including the $location only works if the route is registered here.
  8. Call the method $routeProvider.when() for each route of your application passing the correct parameters
  9. Distribute tags <a href="#/rotaEscolhida">
  10. Utilise $routeParams.qualquerPropriedadeRegistrada as needed.

App running here: http://jsbin.com/roqil/edit

25

From my point of view, all the answers are correct, but no one has remembered another way to do it, using the Angularjs and the recourse to ngView you can do this in a practical and fast way is the angular itself already has support for animations transitional.

Example in Plunker

  • 6

    Agree @R3olon. Angulajs is very good. I used it for a while but I dropped it because it was still very green and the documentation was a little scarce. However, it is now much better; and now with the improved User Interface (UI) part seems to me an excellent option. You’ll need some Javascript skills. Basically, you create different pages for what you need and then Angular takes care of that :)

18

This can be done in many ways. You can use a script to submit requests by ajax by clicking links to the same domain on 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 "json" variable to the query string of the url, which will be used to determine whether the script will generate a json object or the full 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.

13

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>

<div id="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>

Observing: Remember to always put the CSS and Javascript that will be instantiated on the main page. Here is the principle, just format the CSS and create the links, Apply on the site that is making the technology. For the home page, just put 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; });
  • 1

    Set put "href" with the page on the link, the page would overlap.

12

You could use the function "load" of jquery and update certain element of the page, for example, let’s assume that every click on elements with the class "change-content", it uses "href" to search for the new page, and update "#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>

9

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

As far as I know there is no other way than Ajax, which can be done in 3 ways I know, but I will demonstrate the $.load method.:
LOAD
This method works best for the question that the úsuário proposed. I’m going to go into a little bit more detail by applying it to a model. Let’s say on the server you have a folder of a web project called "Project". Inside the project folder we have "index.php", "pagina1.php", "pagina2.php" and so on...
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>

PAGINA1.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 the page1 an updated table should appear in the content. From this example it is possible to imagine what is possible to do using the load.

9

You will need to use AJAX yes, basically you will have a page that will show the contents of other files like about.php, contact.php, portfolio.php through jquery load() or javascript open('GET') and with callback you can trigger the effect you want to.

Look at this script in jQuery (Jsfiddle)

This search 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();
        });
    });
});

7

You can use a switch. 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 index.php page it should contain the receipt of 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.

Then 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
  • Even doing so, there will be multiple requests, always reloading the page every click on the links, so it does not answer the question, which explicitly asks not to upload the page again.

  • Hi Anderson. Thanks for the comment. He said MAYBE the Ajax. This example would be an alternative to keeping all pages in a single file, which is his premise in the question, since he wants a site other than ONE PAGE SCROLL WEBSITE. So in my view, answer yes to the question.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.