I'm trying to fetch content from a php page. I have a fetch call + a history.pushState firing on click, which are both working fine, but window.popstate is returning an error when going back by pressing the browser's back button. The error is, that window.popstate doesn't know what url to fetch when going back.
Unfortunately I can't figure out how to pass the right url variable to window.popstate.
// the code stripped fetch function
var load = function(url){
fetch(url, {
method: "GET"
}).then(function(response) {
response.text().then(function(text) {
// parsing and temporary placing fetched content into a fragment
var content = new DOMParser().parseFromString(text, "text/html"),
bodyPart = content.querySelector('main'),
fragmentElement = document.createDocumentFragment(),
tempElement = fragmentElement.appendChild(bodyPart);
// replacing the current content with the fragment
document.body.replaceChild(tempElement, document.querySelector('main'));
// need to assign the fetch on click function again, otherwise it won't work on the dynamically added (the fetched) links
clickOnPJAXLink();
});
});
}
// the click function if clicking on any link function to start fetching content
var clickOnPJAXLink = function(url) {
document.querySelectorAll('A').forEach(a => {
a.addEventListener('click', (e) => {
e.preventDefault();
var url = e.currentTarget.getAttribute("href");
load(url);
history.pushState(url, "sometitle", url);
});
});
}
// load the function initially on the home page
clickOnPJAXLink();
// popstate for back button
window.addEventListener('popstate', function (e) {
var state = e.state;
if (state !== null) {
load(url);
console.log(url)
}
});
The window.popstate returns the error, that var url is undefined and thus of course cannot fetch the before (the history back) content.
Many thanks for any tips!
history.pushState takes a data object as the first parameter, not a string- try history.pushState({url:e.currentTarget.getAttribute("href")} then e.state.url will equal the url you want to load.
Related
I have created an electron app that fetches a JSON value from https://complimentr.com/api. But, when you click the button to set the innerHTML value to the JSON value, it gives the dreaded 'undefined'.
// create a variable called url and set it to the url of the website
var url = "https://evilinsult.com/generate_insult.php?lang=en&type=json";
// create a variable called response and set it to the response of the get request
request(url, function(error, response, body){
var data = JSON.parse(body);
console.log(data.compliment);
const btn = document.getElementById('button-1');
btn.onclick = () => {
document.body.innerHTML = data.compliment
}
});
Is there any reason this isn't working? I am new at JavaScript so this could be an easy fix.
It should be response.compliment not data.compliment
console.log(response.compliment);
So I have written the following script with a function that handles the pushState call and some jQuery which calls that function onClick:
function pushUrlState(id, url) {
if (typeof (history.pushState) != "undefined") {
var obj = { Id: id, Url: url };
history.pushState(obj, obj.Id, obj.Url);
} else {
alert("This browser does not support HTML5.");
}
}
$(function () {
$("#id1").click(function () {
pushUrlState('Id1', '2017/15/05/my-birthday-is-today');
});
$("#id2").click(function () {
pushUrlState('Id2', '2017/14/05/my-birthday-is-tomorrow');
});
$("#id3").click(function () {
pushUrlState('Id3', '2017/16/05/my-birthday-was-yesterday');
});
});
Works very nicely, but after many clicks of various elements I end up with the following:
http://127.0.0.1:3000/2017/15/05/2017/14/05/2017/16/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/2017/14/05/my-birthday-is-tomorrow
Is there some function that I can call that kills the URL back to the domain?
You pass in a relative url (your url does not start with a /).
https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method
URL — The new history entry's URL is given by this parameter. Note
that the browser won't attempt to load this URL after a call to
pushState(), but it might attempt to load the URL later, for instance
after the user restarts the browser. The new URL does not need to be
absolute; if it's relative, it's resolved relative to the current URL.
The new URL must be of the same origin as the current URL; otherwise,
pushState() will throw an exception. This parameter is optional; if it
isn't specified, it's set to the document's current URL.
Try the following 2 code snippets in the console and see the differences:
This behaves like your code (relative url)
[1,2,3,4,5,6,7,8,9]
.forEach(
num =>
//relative url (does not start with /
history.pushState({}, `page ${num}`, `hello${num}/world${num}.html`)
)
This behaves like you'd like it to behave:
[1,2,3,4,5,6,7,8,9]
.forEach(
num =>
//absolute url start with /
history.pushState({}, `page ${num}`, `/hello${num}/world${num}.html`)
)
I have this code in Backbone.js where I am trying to create dynamically a URL and call a function from the controller which returns a JSON data.
For some reason when doing the fetch() method at the end the URL in my browser does not change.
I have put a console.log in my getdata() function just to see if the call is happening, and it does. Also i have tried to console.log the new build URL with the parameter at the end, and also this is build successfully.
Any ideas why the URL in not changing in the browser?
Thank you
getUrl: function(celebname){
var urlstr = "http://localhost/Codeigniter/index.php/testcontroller/getdatabasedata?searchvalue="+celebname;
return urlstr;
},
events: {
"click #submitbtn" : "getdata",
},
getdata: function (event) {
var celebname = $('#celebname').val();
this.model.url = this.getUrl(celebname);
this.model.fetch();
},
Backbone will always try to use the collection url, so if you want to fetch or save you should explicitly save the model with a new url.
Try overriding the url in the model like so:
var newUrl = this.getUrl(celebname);
this.model.save({}, { url: newUrl});
Instead of just setting this.model.url = this.getUrl(celebname);
I have a php page that displays a list of items, when one is clicked it returns me to the main menu a series of extras get values. These I grab using JavaScript and activate a function. This affects the localStorage very quickly and then I want to switch the url again but for some reason window.location isn't forwarding me at all. If it makes any difference, I am redirecting to the same url just taking away one of the two get values.
Here is the source:
//When the item is initially clicked, I have used alert to make sure there is a valid 'id'
function remo(id) {
window.location = "http://www.example.co.uk/?s=&r=" + id;
}
//When the JS reads the URL for the get values
var rcheck = url.search("r=");
if(rcheck>=0) {var re = getUrlVars()["r"];remove(re);}
//The function getUrlVars()
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,
function(m,key,value) {
vars[key] = value;
});
return vars;
}
//The remove() function called 2 statements ago as remove(re);
function remove(id) {
localStorage['KFAch' + id] = 0;
var url = "http://games.thanetdragons.co.uk/killingfloor/?s=";
window.location = url;
window.location.replace(url);
window.location.href = url;
$(location).attr('href', url);
}
As you can see I am trying extensive redirect options.
Everything works fine, it even switched the localStorage value correctly, except, it doesn't forward my webpage to the next URL that no longer has the r parameter.
Is there any reason for this?
I need to make a function in JavaScript to locate href inside the url that is given, and to return it as a string.
For example: http://stackoverflow.com/
So the function starts with: function example(url) {}
I want to find the first link inside this url that contain the words google.
In this page there is somewhere link like <a href:"http://google.com/asdasdadsa/asdada">
The function is to return the whole link as string.
So basically from what I can gather, you want to look at each link on the page and get the whole URL if it includes some string (i.e. google).
Here's a function that finds the first link matching a certain string:
function checkLinks( searchString ) {
var url;
// Go through each link
$('a').each( function ( ) {
// Check if the search string exists
if( $(this).attr('href').indexOf(searchString) != -1 ) {
url = $(this).attr('href');
// If we've found one, stop the each.
return false;
}
});
return url;
}
I've put together a jsfiddle showing an example of how this function could be used:
http://jsfiddle.net/K9KvS/1/
EDIT:
I've just seen you need to do this on a remote URL. You probably need to use AJAX to load in the code, then run this on the code you have. Unfortunately due to the same origin policy, you can't get this directly, so you'll need to run a server-side script on your server (e.g. using PHP) to load the content of the external page, then an AJAX call from your JS to pull it into your javascript.
Modified version to include an AJAX load of some code, then a find on that code:
// Create a function to do the actual search
function checkLinks( code, searchString ) {
var url;
// Search the code for all <a> tags, the loop over them
$(code).find('a').each( function ( ) {
// Check if there is a match (indexOf returns -1 if not)
if( $(this).attr('href').indexOf(searchString) != -1 ) {
// set the "url" variable to the href
url = $(this).attr('href');
// Stop looping
return false;
}
});
return url;
}
// Now, when the page loads, attach an AJAX call to a button with ID "linkchecker"
$( function ( ) {
$('#linkchecker').click( function( ) {
var code;
// Perform the AJAX call, load the data and call our function above to find "google.com"
$.get( 'load_code.php?url=http://www.google.com', function( data ) {
code = data;
alert( checkLinks( code, 'google.com' ) );
});
});
});
load_code.php would probably look something like this (probably with some error checking, etc):
<?php
$htm = file_get_contents($_GET['url']);
echo $htm;
?>
Update: Using Raw Javascript
We'll modify checkLinks from above to use raw Javascript:
function checkLinks( code, searchString )
{
var url;
// We need to create an HTML document element so we can use javascript dom functions on it.
var doc = document.createElement("html");
doc.innerHTML = code; // put the code into the document
// Get all links in the code
var links = doc.getElementsByTagName("a")
// Loop over all links
for (var i=0; i<links.length; i++) {
// Check if the search string (e.g "google.com") is found in the href of the link
if( links[i].getAttribute("href").indexOf(searchString) != -1 ) {
// Set it to the return value
url = links[i].getAttribute("href");
// stop looping
break;
}
}
return url;
}
So firstly, you need to set up the Ajax request object. The problem is this differs between browsers, so you need an unpleasant bit of code to generate it across them. The following is modified from the tiztag ajax tutorial:
function makeAJAXObject(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
return ajaxRequest;
}
Ok, so now we've got our AJAX object, we want to get it to load a page, and tell it how to handle what we get back:
/*
* A function to load a given URL and process the code from it.
* It takes three arguments:
* php_handler The name of the PHP file that will load the code (or ASP, or whatever you choose to use)
* url The URL to be loaded.
* searchString The string to find in the links (e.g. "google.com").
*/
function load_page( php_handler, url, searchString )
{
// Get the ajax object using our function above.
window.ajax = makeAJAXObject( );
// Tell the AJAX object what to do when it's loaded the page
window.ajax.onreadystatechange = function(){
if(window.ajax.readyState == 4){ // 4 means it's loaded ok.
// For simplicity, I'll just alert this, but you would put your code to handle what to do when a match is found here.
alert(checkLinks( window.ajax.responseText, searchString ));
}
}
// Set up the variables you want to sent to your PHP page (namely, the URL of the page to load)
var queryString = "?url=" + url;
// Load the PHP script that opens the page
window.ajax.open("GET", php_handler + queryString, true);
window.ajax.send(null);
}
The final thing is to attach this to a button when the page has loaded:
window.onload = function( ) {
document.getElementById('linkchecker').onclick = function( ) {
load_page('load_page.php', 'http://www.example.com', 'google');
}
}
Please note, there's likely to be built in WinJS functions to handle some of the AJAX stuff, but I've never tried Win 8 app development, so I don't know them!