Django/JavaScript: passing hidden variables to a page with window.location.href? - javascript

Apologies if this question is a bit convoluted.
I want a Django page to display a banner message sometimes. Sometimes the user will arrive via window.location.href, and then I would like the banner to display, with a message determined by the action the user just performed.
Details:
I have a site-wide javascript listener that listens for scanner input (which presents as keyboard input).
When it triggers, using jQuery I return or check out the item, dependent on its state. I do this via an Ajax POST request.
Then I immediately take the user to the item's page on my site. I do this by setting window.location.href to the item's page, inside the response handler of the POST request. The item shows as available or checked out, but I want to show the user another message too...
...I want to show a banner saying 'Item checked out' or 'Item returned'.
The last item is where I'm having problems: how do I 'tell' the item page what message to show, and when to show a message at all? People will also arrive at item pages not via the scanner.
I could set GET parameters (?t=checked_out or ?t=returned) but that feels messy.
I could use cookies but that feels even messier.
If I POST to the item page (which also feels wrong) with a t=checked_out parameter, wouldn't it be good Django practice to then redirect somewhere else, rather than display the page?
Perhaps I'm just too hung up on the last point.
Anyway, the basic question is: How best can I pass hidden variables to a page via window.location.href?
Thanks for your help. I have the feeling there's something fundamental that I've yet to learn here :)

Why do an AJAX request at all for step 2/3?
You asynchronously POST, then redirect.
Can you do a normal POST with info about whatever the javascript did, add some message in your session in the django backend (and have the item view load it), and do a server redirect to the item page?
The django way would definitely be to do it in django sessions.
If you must, your method should be possible anyways:
pass extra bits of information TO django in your ajax post
set your "hidden variabes" to the django session (request.session['myvar'] = 'ajax_posted_stuff')
javascript redirect (but seriously, it would be best to have the server redirect)
pull "hidden variables" from the django session (ajax_posted_stuff = request.session['myvar'])
Example:
def ajax_view(request):
if successful_response():
request.session['show_banner'] = True
return JSON # or whatever you were doing before
def item_view(request):
context = {}
if request.session.get('show_banner'):
context['show_banner'] = request.session.pop('show_banner')
return render_to_response("mytemplate.html", context)
# item.html
{% if show_banner %}
<h1>Banner shown!</h1>
{% endif %}

Why do you think using a cookie would be messy? I'd say go for cookies if you can. You can read cookies from window.document.cookie.
As an alternative to cookies, the cleanest solution could be to use the URL hash:
http://example.com/page#co
You can easily check for the presence of the hash with window.location.hash.

Related

Is there a way to send POST data to another form and return the result of that form?

I need to send form data to another page that will allow the user to do something in a form and return the result of that form back to the original page? Is this possible? I know it's not ideal, but the issue is that I need to make a "drop-in" solution that does not need to be integrated with other code. I know it's a very specific request and scenario.
I know how to send POST data that doesn't require any user input on the processing page. i.e. I can send POST data to 'calculate.php' which will do the math and send it back, but if I need additional user input on 'calculate.php', how can I still send it back?
An example of expected results would be:
Page #1: User enters a number and presses submit to go to next page.
Page #2: User enters a second number and presses submit to finish.
Back to Page #1: User receives sum of both numbers.
Obviously, this is a really redundant thing to do, but I'm trying to simplify the problem as much as possible.
EDIT: There a few restrictions I forgot to add.
Page #1 is not my application, I am developing Page #2 as a "drop-in" solution for Page #1. Essentially, I can only use Page #1 to call Page #2 and receive a response from it. The problem is that I need to be able to allow for user input on Page #2.
I know I can post to Page #2 and then post to Page #1 again, but what if I need to maintain the state of Page #1. For example, if there's an open Web Socket connection.
Please note, I understand that this may be impossible or extremely difficult, but if I don't ask I'll never know right?
You want it with PHP or any other language. If you are running Php on server side then you can use Global variables like $_GET and $_POST.
Page #1: Use Post/Get method to send data to second page.
Page #2: Receive all fields' values using Globe variables ($_GET and $_POST). You can use these values as default values of form fields. Now submit this data to page 1 using post or get method.
Back to Page #1: Here you will receive the data of first page from second page and newly posted data from page 2
Either of these should work:
Never leave the page - use AJAX / XMLHttpRequest to call out to other pages to process chunks of data
Do everything on page 1 using "postbacks" -- the form targets are the same page, there is a state variable like "stage=1", and you use JavaScript to add set hidden variables for any additional state that's needed.
... PHP state validation and processing for the different stages ...
... one or more blocks of HTML for the page (PHP if / else can be used to choose between multiple page views) ...
Edit for added restrictions:
Have page 2 use postbacks or AJAX to collect the additional information
I figured out a few ways to do it.
Update a Database (or Data Store of some sort, depends on security needs) and have Page #1 listen for events from a separate page (on the same server as the database). Very similar to the way PayPal's Instant Payment Notification (IPN) works. I was actually able to set up server sent events with it as well.
Essentially, Page #1 sends data to Page #2 where the user will perform the function and then Page #2 will send POST data to a listener somewhere (either on the same server or Page #1's server), the listener will update a database and Page #1 will be listening or pulling to an event handler that will send an update once the database updates.
Use JavaScript Child/Parent Window functions. This is okay if Page #1 and Page #2 are on the same server, but can get messy and browsers have a lot of restrictions and it varies depending on browser.
Page #1 will open Page #2 in a child window, after the user performs a function, Page #2 will call a function that accepts the result data on Page #1.

Removing query params causing issue on page refresh

I have a URL with a query string attached to it. After the page loads, I am removing the query param using
history.replaceState("","",location.href.substring(0,location.href.indexOf("?")))
But when user hit refresh button its displaying error screen from my application since expected query param was not there in URL. I can use post action there but I would like to avoid query params with page refresh working fine. Is there any solution for this ?
If you're using a query parameter and then removing it, then the user hit's refresh and there is an error saying it's expecting a query parameter, then your code (and logic) is lacking.
My suggestion, if you want to avoid query parameter after the page initially loaded, is to save the parameter in a cookie or even a session if there is code-behind. Then if the user refreshes without the query parameter, check if the cookie exists, if the cookie exists, show them the page normally, if not, instruct them that they did not visit the URL through the correct channels.
However, like I mentioned, I think your logic here is flawed, because if the user wants to share your URL to the outside world, and you removed the key piece of information that makes the page load successfully, then you will have a lot of confused people on your hands
edit
You might want to investigate SEO friendly URL's to pass your query in to, so instead of: yoururl.com/?firstname=joe you can do yoururl.com/firstname/joe

Refreshing a page with cookies in Play

I have a drop-down selection of available languages. Currently, clicking on a language is mapped to a method in controller which updates the Play Session (which is a cookie under the hood) with the selected language and returns index page.
View:
English
Controller:
def setLanguage(language: String): Action[AnyContent] = Action { implicit request =>
val updatedSession = request.session + (("lang", language))
Redirect(routes.Application.index()).withSession(updatedSession)
}
As you can see, I redirect to index page and it's working fine. However, as the language selection is available at all times on my page, it may be clicked from /resource1, /resource2, /resource3 etc. and I would like to refresh that particular view instead of being returned to home page. I cannot simply get request.uri in the controller and refresh whatever it's pointing to because setLanguage() is mapped to its own route, so my request URI is always /language?lang=whatever.
So, how do I know that prior to invoking GET on /language, client was on, say, /items so I can reload items page instead of returning him to home page? Should I send a GET request with resource as a parameter (e.g. ?lang=en&location=items) to know which page to render? Should I make an ajax request and call window.location.reload() on success? Do I even need to go to server or can I simply update the PLAY_SESSION cookie manually from the client?
I'm using Play 2.3.7.
No you cannot update the PLAY_SESSION cookie from the client side, since it is signed by play with the application secret.
So I think the easiest solution would be, as suggested, to send the current resource as parameter and trigger a redirect.
There is an HTTP header called Referer that contains the url from which the request was made. As far as I know it's supported and used by all modern browsers when you navigate from a page to another.
You can simply redirect to that Referer url.
Another solution is to track in a session or a cookie all pages that are accessed by an user, by using some kind of interceptor in Global.scala or a custom Action builder that you use everywhere. Then in case of language change you can simply redirect to the last page that was accessed by the user.

How can I go to an html page while passing a hidden parameter using Javascript or jQuery?

Upon completion of an ajax call I would like to direct the user to an html page, but at the same time passing a hidden variable (this variable contains sensitive information and should not show up in the URL).
How can I accomplish this?
window.location.href = 'userpage.html?id=14253';
But with the id remaining invisible? Can I POST the id somehow while sending the user to userpage.html?
You should not be checking user credentials on the client side of your website. Regardless of how the ID is being passed to your script, it can be replicated without you being able to check if the request is valid.
To start being even remotely secure with what information is granted to a user, you need to be checking it via the server side. With every request, ensure the user is authenticated to view such data.
If I were you, I would look into using PHP sessions as the first line of defense for checking if a user is authenticated. Doing so will at least keep the information about a user out of a replicable space that can be viewed by the user.
Look up 'php session login tutorial' on Google and you will find plenty of simple tutorials which should get you on the right track.
Example Tutorial
No matter what, the information you pass along is insecure. You can submit a post request using XMLHttpRequest objects if you'd like (or use a framework/library to make AJAX calls) -- but the user could still spoof the data and get different results.
ID enforcement should be done in the backend. Does the requested ID match the ID of the user signed in? No? Don't show it. etc etc.

header(Location:) via AJAX not redirecting

First off, let me say that I know this does not seem like an uncommon issue. I do not intend to clutter these forums with questions that have already been answered, but, I have worked through probably about 3 dozen threads with similar issues and have been unable to reach a solution.
The short description of my issue is this: I am trying to redirect after submitting a form using php's header(location:) function, and it's not redirecting. It is a little bit complicated because the form is submitted via AJAX. The steps my code goes through are as follows:
User submits form > form data sent via AJAX > form processing page validates data > if valid, form processing page inserts data into database > if submission is successful, form processing page adds redirect URL to $_SESSION > form processing page returns a 'redirect' variable > javascript/AJAX checks for redirect variable, and refreshes page if found > page header checks $_SESSION for redirect URL, and if found, sets appropriate headers and exits.
I guess the first thing I want to ask is, is this the right way of going about this? It seems to me that there should be a simpler way of doing this. It's obviously much simpler to pass the redirect URL to the javascript and do a window.location redirect, but I read that it's much better/more secure to handle that on the server side, so I'm trying to do that.
Assuming I'm going about this in the right direction, what could be going wrong here? I've checked for leading and trailing whitespace, BOM characters, I've even tried output buffering and I still have the same issue.
What happens on form submission is, the page refreshes, but it returns to the original form page rather than the redirect url. I have turned on the most detailed error reporting and get no errors at all.
One thing that may or may not be of interest, I have an error_log function set up to log all headers to a file right after I set the Location: header. When I redirect outside of AJAX (which works), the accept: header is set to html, but when I try to do it via AJAX, the accept header is set to JSON. Could that cause a problem?
Thank you so much for taking the time, and again, apologies if this is a dumb question. I have used this forum for years and have never once had to post a question on it because it has always solved my problems until now. Thanks in advance!
PHP is too generous to include in your code not only HTML code, but also JavaScript code. I'll explain one thing. When you send data by ajax, it is often difficult return Boolean data (whether true or false, depending on the conditions we work side server with php in some file established in our direction ajax) to give a final answer.
On the other hand, returning to the generosity of PHP, always when we try to validate data server-side and through ajax, we can manipulate the section where work freely to show some response message, a redirect to somewhere on your page or create a session. Anyway, whatever.
What I mean is that in your controller section where you will work with AJAX, you can set different conditions. That is, if the user data are correct, then you could send to call a script from Javascript to redirect him with a location.reload (); and also assign a session automatically. If the user does not have the correct data, then what we should do is return a warning message or alert to the exit AJAX, usually it goes after a:
function (response) {
$ ('.answer').html(response);
}
Note that it is not necessary require, for example, a $ ('.answer').html(response); to return an answer, because ajax only sends data to the server and if there is a reply message well, and if not well. Many times what I do, is to send messages via console, although it is often convenient to do so, because as often work with several conditions and that depends on the result of our request, we will be forced to show some response in some element within our code.
What I advise you is that you work javascript in PHP, and hence redirect to other pages, assign sessions or simply return a message. Remember that an ajax request is not only asynchronous, but repetitive and can send it to call as often as you need. The fact that you sent your ajax call php file and you have returned an answer, does not mean you can go back to work with it once you finish your ajax request.
It is the right way to do what you want, it is often easier to manipulate our server-side code that client side. Greetings.

Categories

Resources