pushState doesn't make a request, it just changes the url and stores a new history entry. Thinking about this concept, it's impossible to refresh or bookmark because the server will always do a request. A server-side solution is needed.
After several hours searching, I have found a solution, every single call must be redirect to index.php to let PHP handle the request.
rewrite ^/(.*)$ /index.php?page=$1 last
I don't know exactly how this file should be to let a website refresh or bookmark a page. Can somebody help me ? I made an example to help clarify.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<title>History API</title>
<script>
function ajax (url, callback) {
var conection = new XMLHttpRequest ();
conection.open ("GET", url, true);
conection.setRequestHeader ("X-Requested-With", "XMLHttpRequest");
conection.send (null);
conection.onreadystatechange = function () {
if (conection.readyState === 4) {
if (conection.status === 200) {
callback (conection.responseText);
}
else if (conection.status === 404) {
alert ("Page not found !");
}
else {
alert ("Error !");
}
}
}
}
window.addEventListener ("popstate", function (event) {
var state = event.state;
if (state) {
document.getElementById ("content").innerHTML = state["content"];
}
});
document.addEventListener ("DOMContentLoaded", function () {
var content = document.getElementById ("content");
var menu = document.getElementById ("menu");
menu.addEventListener ("click", function (event) {
var target = event.target;
if (target.nodeName === "A") {
ajax (target.href, function (result) {
history.pushState ({"content": result}, target.innerHTML, target.href);
content.innerHTML = result;
});
event.preventDefault ();
}
});
});
</script>
<style>
body {
width: 400px;
}
div {
border: 1px solid black;
padding: 10px;
}
</style>
</head>
<body>
<div id = "menu">
Page 1
Page 2
</div>
<div id = "content"></div>
</body>
</html>
index.php
<?php
isset ($_GET["page"]) or exit ("Error !");
$page = $_GET["page"];
// Ajax request
if (isset ($_SERVER["HTTP_X_REQUESTED_WITH"]) && strtolower ($_SERVER["HTTP_X_REQUESTED_WITH"]) === "xmlhttprequest") {
if (file_exists ($page)) {
require_once ($page);
}
else {
header ("HTTP/1.1 404 Not Found");
}
}
else {
require_once ("index.html");
}
?>
page1.html
Hello, I'm the Page 1. It's nice to meet you.
page2.html
Hi brother. I'm page 2.
Clicking (ok)
Refresh (fails)
First of all you should really not use a GET parameter as input for a _require_once_. Really. Not. Use at least a simple whitelist of allowed names for pages and only include and output mapped files (or files with those whitelisted names).
Now to your history API problem. Pushing things obviously seems to work for you so all that is missing is probably a simple ondomready event that reads the current URL and loads the content via AJAX or from existing history entries. The same whitelist approach should be used there. Also try to not fall into the trap of DOMXSS by using unvalidated input (the URL) as input for your javascript and DOM operations.
Related
i am try to load B.php from A.php after execution in the function and pass some data using a post array from A.php to B.php within same time.
code list as follows
A.php
<script type="text/javascript">
alert_for_the_fucntion();
window.location.href = "B.php";
function alert_for_the_fucntion() {
$.post("B.php", {action: 'test'});
}
</script>
B.php
<?php
if (array_key_exists("action", $_POST)) {
if ($_POST['action'] == 'test') {
echo 'ok';
}
}
?>
for testing purpose i tried to echo something in the B.php. but currently this is not working. have i done any mistakes? or is there any possible method to do this.
Your code does this:
Tells the browser to navigate to B.php (using a GET request)
Triggers a POST request using XMLHttpRequest
The POST request probably gets canceled because the browser immediately leaves the page (and the XHR request is asynchronous). If it doesn't, then the response is ignored. Either way, it has no effect.
You then see the result of the GET request (which, obviously, doesn't include $_POST['action']) displayed in the browser window.
If you want to programmatically generate a POST request and display the result as a new page then you need to submit a form.
Don't use location. Don't use XMLHttpRequest (or anything that wraps around it, like $.ajax).
var f = document.createElement("form");
f.method = "POST";
f.action = "B.php";
var i = document.createElement("input");
i.type = "hidden";
i.name = "action";
i.value = "test";
f.appendChild(i);
document.body.appendChild(f);
f.submit();
If you want to process the results in JavaScript then:
Don't navigate to a different page (remove the line using `location)
Add a done handler to the Ajax code
e.g.
$.post("B.php", {action: 'test'}).done(process_response);
function process_response(data) {
document.body.appendChild(
document.createTextNode(data)
);
}
Try this:
Javascript:
<script type="text/javascript">
window.onload = alert_for_the_fucntion;
function alert_for_the_fucntion() {
$.post("B.php",
{
action: 'test'
},
function(data, status){
if(status=="success"){
alert(data);
}
}
);
}
</script>
PHP
<?php
if(isset($_POST['action'])){
echo $_POST['action'];
}
?>
The following Ajax works , but it takes a while just to notify user on the client side that the username is already taken. Is there any ways to fasten this respons, or it's just normal behavior of Ajax.
Client :
<title>Choose a username</title>
<style>
#targetDiv {
background-color: #FF9999;
width: 40%;
}
</style>
<script type = "text/javascript">
var XMLHttpRequestObject = false;
if (window.XMLHttpRequest) {
XMLHttpRequestObject = new XMLHttpRequest();
} else if (window.ActiveXObject) {
XMLHttpRequestObject = new ActiveXObject("Microsoft.XMLHTTP");
}
function getData(dataSource)
{
if(XMLHttpRequestObject) {
XMLHttpRequestObject.open("GET", dataSource);
XMLHttpRequestObject.onreadystatechange = function()
{
if (XMLHttpRequestObject.readyState == 4 &&
XMLHttpRequestObject.status == 200) {
if(XMLHttpRequestObject.responseText == "taken"){
var targetDiv = document.getElementById("targetDiv");
targetDiv.innerHTML = "<div>That username is taken.</div>";
}
}
}
XMLHttpRequestObject.send(null);
}
}
function checkUsername(keyEvent)
{
keyEvent = (keyEvent) ? keyEvent: window.event;
input = (keyEvent.target) ? keyEvent.target : keyEvent.srcElement;
if (keyEvent.type == "keyup") {
var targetDiv = document.getElementById("targetDiv");
targetDiv.innerHTML = "<div></div>";
if (input.value) {
getData("check.php?name=" +input.value);
}
}
}
</script>
</head>
<body>
<H1>Choose a username</H1>
Enter your new username <input id = "textField" type = "text"
name = "textField" onkeyup = "checkUsername(event)">
<div id = "targetDiv"><div></div></div>
</body>
</html>
Server
<?php
if ($_GET["name"] == "steve"){
echo "taken";
}
else {
echo "ok";
}
?>
Your question is "how to fasten the response".
The response is send by your server over the net.
The time taken for the net transfer will always vary.
But you can try to get faster responses of your server by optimizing the configuration of the webserver and PHP. You can test the response behavior of your server with a benchmark tool like abor siege.
And then tweak, test, compare results, repeat-until-satisfied.
A request to the server is a request to the server. No matter, if it is done by a browser via ajax or the benchmark tool.
For instance, upgrading to PHP 5.6 and enabling and tuning the opcache, gives quite a performance boost, when compared to let's say PHP 5.3. There a lot of optimizations possible. The question is too broad to go into detail.
When looking at the client-side JS: this is plain-vanilla JS.
Not much room for improvements. The only thing which comes to my mind is
to change the xhrObject for IE from "Microsoft.XMLHTTP, which is really old, to new ActiveXObject("Msxml2.XMLHTTP.6.0"); (and maybe add a fallback to new ActiveXObject("Msxml2.XMLHTTP.3.0");).
It will always take some time to get the respond from the server, you can tune up your server to be faster but you will always have a delay.
However what you can do is show a loading splash while you are connecting with the server.
You can also try storing usernames in Memcached as it will reduce the time taken for sql query.
I have a simple AJAX based site that I have an equally simple geolocation function that redirects a user to a new page when they click a button.
This is the part of my geolocation function that redirects users which, as you will see, redirects people to a page called weather.php;
function showPosition(position) {
window.location='weather.php?lat='+position.coords.latitude+'&long='+position.coords.longitude;
}
The problem is that it redirects the page using a "traditional" page load and thus renders the AJAX page loading I have implemented obsolete.
Is it possible to modify this function and make it AJAX friendly?
This is the full redirect code;
<button onclick="getLocation()">My Location</button>
<script>
var x = document.getElementById("message");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, showError);
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
}
}
function showPosition(position) {
window.location='weather.php?lat='+position.coords.latitude+'&long='+position.coords.longitude;
}
<script>
Here is how you can do it.
I give you a simple example of a website where the pages are loaded with Ajax. The page is put in the url.
Not like this: weather.php?lat=50.452
But like this: index.php#50.452
The point is: when you change anything right of the #, the page is not reloaded.
And still, there is a system where the url remembers the page
It's not a complete answer to your question, but I hope it gives you the inspiration you need
pages.php
<?php
switch(isset($_GET['p']) ? $_GET['p'] : '') {
default:
$content = 'This is the HOME page ...';
break;
case 'calendar':
$content = 'calendar stuff ...';
break;
case 'contact':
$content = 'contact stuff ...';
break;
}
echo $content;
?>
index.php
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
// load page according to the url.
// We read the url, to the right hand side of the # (hash symbol)
var hash = window.location.hash;
var page = hash.substr(1); // this removes the first character (the #)
loadPage(page);
// triggered by the navigation.
function loadPage(page) {
getAjaxPage(page);
}
// this returns the content of a page
function getAjaxPage(page) {
switch (page) {
default: // = HOME page
var url = '';
case 'calendar':
case 'contact':
var url = page;
}
$.ajax({
url: 'pages.php',
data: {
p: url
},
success: function(data) {
$('#content').html(data);
}
})
}
</script>
<style>
#content {
margin: 15px;
}
</style>
</head>
<body>
<div id="nav">
Home |
Calendar |
Contact |
</div>
<div id="content"></div>
</body>
</html>
Your job ... You should not redirect the client.
It's (something like) a Google Maps thing, right?
What are your intentions there?
Why can't you load weather.php with Ajax? I bet you can.
I got a script to check if a URL is present in a page. Here it is:
class LP_backlinkchecker
{
var $url;
var $content;
var $links;
var $linktocheck;
function __construct($url, $linktocheck)
{
$this->url = $url;
$this->linktocheck = $linktocheck;
}
function SetLinktocheck($link)
{
$this->linktocheck = $link;
}
function getContents()
{
$this->content = file_get_contents($this->url);
}
function lpFetchLinks()
{
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
preg_match_all("/$regexp/siU", $this->content, $matches);
$this->links = $matches;
return $matches;
}
function check()
{
foreach($this->links[2] as $key => $url)
{
if($url == $this->linktocheck)return TRUE;
}
return FALSE;
}
}
My problem is that the script only works for checking links on the same site. It does not work when the links to check is outside of the website. For example, the script works well to check the link
http://web.com/linktocheck present on the website http://web.com/
If think my $regexp is wrong, do you have some idea of the problem ?
Thanks for your help.
Not sure if I have misunderstood your issue but your code seems to work for me. I wrote you a little unit test that you can now have and expand upon, if you could write a test that does not work I might be able to help more.
class LP_backlinkcheckerTest extends PHPUnit_Framework_TestCase
{
public $l;
public function setUp()
{
$this->l = new LP_backlinkchecker('test.html', null);
}
public function tearDown()
{
}
public function testGetContents()
{
$this->l->getContents();
$this->assertNotEmpty($this->l->content);
}
public function testlpFetchLinks()
{
$this->l->getContents();
$matches = $this->l->lpFetchLinks();
$expected = array(
"http://google.com",
"http://www.bluesnews.com",
"http://www.bluesnews.com/somepage"
);
// 4 things captured by the regex
$this->assertEquals(4, count($matches));
$this->assertEquals($expected, $matches[2]);
}
}
and the HTML file I am using
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
Google.com
BluesNews.com
somepage
</body>
</html>
Although it would be better to make your class so that I don't have to supply it a file but that's the way you designed it. I would also suggest perhaps using parse_url to breakdown the url into it's component parts. Your problem may be just that your expecting one string to be equal to the other and there may be a user input error at construct time which your not checking at all.
I have searched extensively for the javascript code to redirect to a different page on the same site and in the same folder and I have tried numerous things. I'm unable to get it to work in localhost or on the web-server. This is what I've tried:
<script type="text/javascript">
function confirm_submit()
{
var con = confirm("Submit form and print invoice?");
var url = 'dashboard.php?del=no';
if (con == true) {
document.location.href = url;
/*I have also tried:
window.location = 'dashboard.php?del=no';
window.location.replace("dashboard.php?del=no");
window.location.href = "dashboard.php?del=no";
*/
}
else {
return false;
}
}
</script>
This is the code on the button :
onclick="return(confirm_submit())"
From everything I've read this should work but it is not working. Can someone please tell me why it is not working and what I need to do to make it work? Thank you in advance.
EDIT: I have answered the question below. It's a workaround, but it is doing the job.
this will work without submitting your form
var url = window.location.href;
splitUrl = url.split("/");
splitUrl[splitUrl.length-1]="your page";
url = splitUrl.join("/");
window.location.href = url;
I have spent too much time on this issue so I have decided to go a different route. I'm using javascript to change the value of a hidden field and then using PHP to redirect to the other page as a result of the posted value of the hidden field. Thanks to all who have given their time to this matter on my behalf. Cheers
<script type="text/javascript">
function confirm_submit()
{
var con = confirm("Submit form and print invoice?");
if (con == true) {
document.getElementById('bool').value = true;
$("#edit_workorder").submit();
}
else {
return false;
}
}
</script>
And the PHP is:
if($bool == true) {
header("Location:dashboard.php?del=no");
exit;
}
It's doesn't really answer the question, but it works and that is more important to me right now.