Update the document.referrer via history.pushState() - html

I'm using pushStates in my ajax-app to navigate from one "page" to another. Now, I'd like to see from what page I was coming from. But document.referrer always returns "". Or, when I open my app from another page (where it is linked), I got the URL from that other page.
Shouldn't these lines...
history.pushState({}, "Some title", "/some/valid/url/1");
history.pushState({}, "Some title", "/some/valid/url/2");
...produce a referrer like this:
http://somedomain.com/some/valid/url/1
?
Or in other words: Is there any way to set the document.referrer accordingly, or at least reset it to ""?
Note: I'm looking for solutions without caching the previous URL in some variable. I need something that really changes the document.referrer, because I cannot change the scripts that rely on it.

Short Answer: use window.location instead of history.pushState
Longer Answer:
document.referrer according to MDN: "The value is an empty string if the user navigated to the page directly (not through a link, but, for example, via a bookmark)"
Directly manipulating the history state will not be treated as following a link. You can simulate a link click by update window.location (MDN) which will also update the history automatically.
For example, load a tab with https://github.com/kanaka/mal/. Then type the following one line at a time (otherwise they are all run in a single javascript execution context and only the last location update applies)
console.log(history.length) // 2
console.log(document.referrer) // ""
window.location = "/kanaka/mal/tree/master/ada"
console.log(history.length) // 3
console.log(document.referrer) // "https://github.com/kanaka/mal"
window.location = "/kanaka/mal/tree/master/python"
console.log(history.length) // 4
console.log(document.referrer) // "https://github.com/kanaka/mal/tree/master/ada"

Related

Modify form navigation via script

I want to use a script to change the behavior of an existing Google Form so that after completing page 1, future respondents will go to another page (say, page 3).
I know this involves using .setGoToPage(), but I don't how to set the parameters to make this modification.
Take into account that the pages in the form are already created, so I just need to indicate that page 1 should go to page 3. To clarify, my problem is that I need to find "page 1" without its name being known so that, afterwards, I can apply the ".setGoToPage(pageThree);" command to page 3 (whose name is also not known).
The real goal here is actually to set page 1 to go back to itself so that no one can see the options of page two, essentially blocking the form from being used. I just worded it this way to be able to undo it later on. It must be a script because it will be added to another script that does other things. I cannot go into the form and do this manually.
function myFunction() {
var form = FormApp.openById("ID GOES HERE");
var item = form.getItems(itemType);
// here is where I need the rest of the script
.setGoToPage("PAGE THREE GOES HERE");
}
Good news, bad news. First the good news.
You were on the right track; you can get all the page break items via Form.getItems(FormApp.ItemType.PAGE_BREAK), which will result in an ordered array of sections. The "first page" (section 1) ends with page break #0, the second with page break #1, and so on.
So modifying the form to go to section 3 after section 1 is easy:
function myFunction() {
var formId = '--form-id--';
var form = FormApp.openById(formId);
var pageBreaks = form.getItems(FormApp.ItemType.PAGE_BREAK);
pageBreaks[0].asPageBreakItem().setGoToPage(pageBreaks[1].asPageBreakItem());
}
Don't forget the .asPageBreakItem() calls, since the results from .getItems() are generic Items, but you need a PageBreakItem specifically, in order to use .setGoToPage().
Now the Bad News... Sections end with page breaks, so there is none to set as a destination for the first section.
However, since you want to effectively disable the form, you could just stop accepting responses.
function myFunction() {
var formId = '--form-id--';
var form = FormApp.openById(formId);
form.setAcceptingResponses(false);
}
Excellent Mogsdad. I could not use the second option you gave because the goal is to make sure the users cannot see the rest of the form, because the form essentially is an exam, so just turning off responses would be insufficient.
BUT, you indirectly solved the problem because what I did was put an empty extra page in between page one and two (making page two really page three) and used your script but slightly modified and it has achieved what I was aiming for.
function myFunction() {
var form = FormApp.openById('FORM ID HERE');
var pageBreaks = form.getItems(FormApp.ItemType.PAGE_BREAK);
pageBreaks[0].asPageBreakItem().setGoToPage(pageBreaks[0].asPageBreakItem());
pageBreaks[1].asPageBreakItem().setGoToPage(pageBreaks[0].asPageBreakItem());
}
Grab page 2 and setGoToPage to FormApp.PageNavigationType.RESTART.
Page 2's pageNavigationType is where page 1 goes after you complete it without choosing an option that redirects you. To go to page 1, use FormApp.PageNavigationType.RESTART. To go to any other page, use that page as a pageBreakItem.
I realize this topic is nearly three years old but, as there is a better answer, I thought I'd reply for anyone who stumbles across it.

How to use pushState,replaceState and popState correctly?

I'm trying to use the history API but I can't get it working as I'd expect. I've look at several examples but they all appear to be doing something wrong. That is, this flow doesn't work as expected:
On new page call pushState
On popState load desired page
What I'm finding happens is that for #2 the URL is not modified to the old state (testing in Firefox). Unless I call pushState, or replaceState again the URL stays where it was. I'm also finding that somehow the first page ends up duplicated in the browser's history (holding down back I can see it).
How exactly should the history be used so that Back/Forward/Reload all work like a traditional page flow?
The problems I'm having relate to the use of an iframe in the page. Each change of the location of the frame creates a new history entry which messages with the desired history. To prevent this one must replace the iframe location instead of assigning a new one.
document.getElementById('content_frame').contentWindow.location.replace( new_path )
Location.replace doesn't create a history entry.

How to handle popstate when url ceased to exist?

I would like to be able to do two things with html5 popstate, I'm not using any plugins just these two methods:
Push State:
function contentLoaded(...) {
...
window.history.pushState({ pageUrl: url }, url, url);
...
}
Pop State:
$(window).bind("popstate", function (e) {
if (event.state) {
loadContent(event.state.pageUrl);
}
});
Now if I delete a record, I want to avoid popping a state which couldn't be loaded, just skip it and try popping the next one.
The second question would be: How can I avoid try popping from an empty stack (I have a back button inside my app, but I can get rid of it with an appropriate reason), but keeping clear if the content couldn't be loaded OR if there is no more items in the stack.
History is not meant to be changed afterwards. You should separate the push/popstate functionality from the content loading functionality; think the "router" or "navigator" pattern in typical client-side mvc framework. If a state has become invalid, the content loading code can "redirect" to another state (by calling pushState), just as you would do in regular server-side app.
Just to remind, a client-side application should work identically whether the state was internally popped or the page was actually loaded using the same url, i.e. the HTML5 history support must be transparent, or in other words, the url alone must contain all the information to construct a particular view (but in the case of popstate, we can cheat and reuse the existing state to speed up things).

Chrome extension attach properties to each tab

In a chrome extension, I've created tab properties that I'm trying to store with each tab. What is the best way to do this? I've looked into using localStorage, but it seems like there could be an easier way. The data is by no means permanent, it only exists as long as the tab does.
There's definitely no need to use localStorage. Without the notion "data is by no means permanent", one already knows that: tab IDs are unique within a session. From this fact, it follows that the data is non-persistent.
The best method to implement it is to maintain a hash of tab properties:
chrome.tabs.onCreated (optional, add initial info to tab hash)
chrome.tabs.onUpdated - (Add/) Update tab hash (URL is available)
chrome.tabs.onRemoved - Remove hash entry
Tab objects are not expensive: All properties are primitives (booleans, numbers, strings).
For instance (background page only):
var tabStore = {}; // <-- Collection of tabs
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
tabStore[tabId] = tab;
});
chrome.tabs.onRemoved.addListener(function(tabId) {
delete tabStore[tabId];
});
IMPORTANT ADDENDUM to Rob W's answer.
Make sure to also listen to tabs.onReplaced as well, and update the tabStore accordingly.
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
tabStore[addedTabId] = tabStore[removedTabId];
delete tabStore[removedTabId];
});
Chrome can change the id of a tab under the hood without warning or signs. As far as I know, the only place that this happens is the Google "instant search" when you type in a search into the address bar. It may be an edge case, but if you don't track this, it could end up being a very insidious problem.

Go to specific line number on a page using # but not in url

I have a record set with hundreds of rows. when a user clicks the row they go somewhere else and later get redirected to the page with the rows again. I want the page to start on the exact row the clicked on.
I have rows set up with a line number corresponding to each record number from the database.
//some record set
while not RS.eof
<a name="<%=line%>">
//other stuff
Rs.movenext
Line = line + 1
wend
when you put '#' in the url and a number it goes to the line number. However, my issue is that the url is off limits. I have the line number stored as a Session variable that happens after they initially leave the page. How can i get the page to go to the line number using the session variable and not the url?
As far as I know, anchor names are a feature of the browser. But there are possibly some Javascript libraries that can scroll down to an anchor name without needing the url.
Here's an SO Question on how to programatically scroll down to a certain location.
I think this works also but I haven't tested it
window.location.hash = "#anchorname";
If you can't do anything with the URL, your best (only) bet is JavaScript on the client.
function scrollTo(row) {
window.location.hash = "#" + row;
}
And call that in body.onload, for example. Put the value of your session variable into the function call.
I don't think you need anchors for this. You can capture the scroll position as a post a request variable and set it back with JavaScript in the page load.
The second option in the post is not specific to asp.net.
https://web.archive.org/web/20211020140248/https://www.4guysfromrolla.com/articles/111704-1.aspx