hashing and pushstate in jquery ajax - javascript

I have 3 buttons
<div onclick="javascript:newmessage()" class="mailcontents">New Message</div>
<div onclick="javascript:inboxmails()" class="mailcontents">Inbox</div>
<div onclick="javascript:sentmailsbox()" class="mailcontents">Sent</div>
and the divs where the content has to be displayed
<div id="inbox"></div>
<div id="sent"></div>
Onclick of each I am changing the content by calling the respective functions
var times = 0;
function inboxmails(){
times++;
location.hash = times;
$('#inbox').empty();
$('#sent').empty();
$('#newmessage').empty();
$.ajax({
success: function (data) {
$('#inbox').append('inbox data');
}
});
}
function sentmailsbox(){
times++;
location.hash = times;
$('#inbox').empty();
$('#sent').empty();
$('#newmessage').empty();
$.ajax({
success: function (data) {
$('#sent').append('sent data');
}
});
}
function newmessage(){
$('#inbox').empty();
$('#sent').empty();
$('#newmessage').empty();
$.ajax({
success: function (data) {
$('#newmessage').append('new message data');
}
});
}
I have also added hashing which adds hash tag and a numberical value to the url
Here is the plunker code https://plnkr.co/edit/tTMzTFIHD03pkIt4CkHO?p=preview
But when I click on the back button of browser it must reload the previous ajax content. i.e, if I click on inbox, it displays inbox data and next I clicked on sent, it displays sent data, and then when I click the browser's back button it must display inbox content inbox data i.e, the previous content.
I understood how to change a url using hashing. But I am unable to understand and also could not find a proper example to pushstate i.e push history back / display the pervious ajax content.
I have checked various examples. But I am not understanding how to go to load ajax content using hashing.
Please help !!!
Thanks in advance !!!

You've not bound any function to a hashtag change event. In JavaScript you could use this event to fire off the AJAX call again:
window.onhashchange = doThisWhenTheHashChanges;
See Mozilla
There is also this JQuery library you can look at which addresses cross browser compatibility issues and a full list of alternative solutions

Related

Control whether a link is clickable or not

I want to control whether a link is clickable or an error should be displayed (Based on result of an ajax call).
<a class="lnkCustomer" href="http://localhost/viewcustomer" target="_blank" data-customerno="237">View</a>
I get to the point where I am able to set the link as "allowed to be clicked":
// Authorized
anchor.data("authorized", true);
However when I run this code, the link still does not open. Ideally once the ajax call is complete, it should invoke the click event. I believe the issue is in this line.
// Trigger Anchor
anchor.click();
This is the entire code:
<script type="text/javascript">
$(".lnkCustomer").click(function(e)
{
var customerNo = $(this).data('customerno');
var anchor = $(this);
// Check for authorized
if (anchor.data("authorized"))
{
return true;
}
$.ajax(
{
url: 'http://localhost/checkcustomer',
type: 'POST',
dataType: 'json',
data: { customerNo: customerNo },
cache: false,
success: function (result)
{
if (result.success)
{
// Authorize
anchor.data("authorized", true);
// Trigger Anchor
anchor.click();
}
else
{
// Show a message in a alert or div
alert('Not authorized');
}
}
});
// Default to false (Do not process anchor)
return false;
});
</script>
Notes: I am using class instead of id in the anchor because I have various links that will trigger this event. However as you can see, this should not be an issue since I am always referring to the individual object:
var anchor = $(this);
You cannot open a new tab without popups enabled or the user's click for that event.
You cannot delay it with promises or invoke a trusted click event.
If you want to verify a user can click your link, then do the API request on page load and store the result.
Or make your link into a button with a two click process for checking and then opening.
There is a simple answer : you can't trigger a click if it doesn't come from a trusted event (change, click, dblclick, mouseup, reset, submit).
Here you are trying to trigger a click after an AJAX (asynchronous) request, which is not allowed.
More info here.
As suggested you could replace it by window.open(href, '_blank'); but beware it could also be blocked by the browser parameters.
Unfortunately, as others mentioned, href cannot be delayed. I did find a work-around to suit the particular scenario. I created an intermediary page when user clicks on the href. This page then performs the ajax request (server side), if it is validated it goes on and display the resource. Otherwise it displays an error and stays on the intermediary page.
Anytime you want to override a browsers default action, you need to call .preventDefault() at the top of the event listener.
After that, since you're server side validating the link every time it's clicked, there's really no reason to store it's state client side. Instead of trying to re-click the link, you could just call window.open(), which is what achors do by default.
$('.lnkCustomer').on('click', function(e) {
e.preventDefault(); //makes anchor click do nothing
let href = this.href;
//pretend this is the call back from your ajax call
//$.ajax(
// success: function(result) {
if (result.success) {
window.open(href, '_blank'); //what an anchor click does when not prevented
} else {
alert('Not authorized');
}
});
Try triggering click like this: anchor[0].click(); and see if that works.
For readability, you can save a reference to DOM element of anchor, not just the jQuery object:
var anchor = $(this);
var anchorEl = $(this)[0];
and trigger click using the DOM element:
anchorEl.click();
I think we cannot overwrite the default behavior of the anchor tag but we can work around it. In this solution, I have replaced href with data-link. And mimic the anchor mechanism with window.open.
Code :
<a class="lnkCustomer" data-link="http://localhost/viewcustomer1" data-customerno="111" data-auth>View</a>
<a class="lnkCustomer" data-link="http://localhost/viewcustomer2" data-customerno="237" data-auth>View</a>
<a class="lnkCustomer" data-link="http://localhost/viewcustomer3" data-customerno="237" data-auth>View</a>
<script type="text/javascript">
$(".lnkCustomer").click(function (e) {
var customerNo = $(this).data('customerno');
var linkToGo = $(this).data('link');
var anchor = $(this);
// Check for authorized
if (anchor.data("authorized")) {
var win = window.open(linkToGo, '_blank');
}else{
$.ajax(
{
url: './checkcustomer.php',
type: 'POST',
data: { customerNo: customerNo },
cache: false,
success: function (result) {
if (result == 'authorized') {
anchor.data("authorized", true);
//new code
anchor.attr("href", linkToGo);
anchor.click();
// Dont us this due to popup blocker
//var win = window.open(linkToGo, '_blank');
}
else {
// Show a message in a alert or div
alert('Not authorized');
}
}
});
}
});
</script>
Please note :
New note for security: As you can see we are using quite a visible data-link and anyone with enough effort can visit the link whether it is authorized or not. If the above answer gets you through the popup blocker, the next few things you can do is maybe only fetch accessible links from the start
OR add a "show links" button and then fetch only accessible links to the user. You can do it via ajax. and also you will not need this JS/Jquery code.
OR assign a random number to data-link and then fetch in your PHP code see if it is authorized if it is then only return accessible HTTP link. many ways to improve.
You can use CSS to style the anchor tags, which I have not in the solution
One method I tried was with use of preventDeault, but it do not work
AFAICT you are 90% of the way there, you're just missing a few key details.
Working JSFiddle.
e.preventDefault(): As already mentioned in other answers/comments, you need to prevent the default action which the event triggers, otherwise the browser will just begin the process of navigating to the link while your JS is still running.
anchor.click() will trigger a click on your link, which will ... start the whole process again! You'll get stuck in a recursive loop. The click is done, you now want to navigate. To open a new window in Javascript, use window.open(href, '_blank');
If your link is already authorised, you need to do the same as if the AJAX authorises it the first time around. Instead of return true;, you need to do the same window.open() again.
Also a suggestion - the convention for using GET or POST is:
use POST when changing data, eg creating a user, or making a purchase, logging in - something which should not happen 2x if you hit reload;
use GET when viewing data, no state changes, no harm in reloading;
AFAICT you are simply querying some customer details, so this should be a GET request.
I've modified you code to work with JSONPlaceholder - a dummy REST API which provides JSON data for this kind of situation (where we need to test an AJAX call with a working response), so we can simulate your AJAX call. It only accepts GET requests, so I've changed your POST to GET, and I've updated the test of the response based on the dummy data it sends back. You can see the output we're working with for User ID 1, and User ID 2.
Since you need to do the "go to the link" chunk of code in more than one place, I extracted that to a function you can call, so we don't need to duplicate that code in several places.
I also added a few extra alerts so you can be sure of what is happening.
See it all in action on JSFiddle.
Javascript:
// A function to actually open the new page, since we need to do this in
// more than one place.
function goToLink(anchor) {
let href=anchor.attr('href');
window.open(href, '_blank');
}
$(".lnkCustomer").click(function(e) {
// Prevent the default action this event would normally trigger from
// happening - in this case, navigating to the target href.
e.preventDefault();
var customerNo = $(this).data('customerno');
var anchor = $(this);
// Check for authorized, and open the link if so
if (anchor.data("authorized")) {
alert("Already authorized, let's go!");
goToLink(anchor);
}
// https://jsonplaceholder.typicode.com/ is a dummy REST JSON generator.
// Let's use it to simulate your AJAX call. User ID 1's username is Bret,
// user ID 2's username is Antonette. Let's use customerNo in the URL to
// retrieve user ID 1 or 2, and simply allow the click if the username is
// Antonette.
// First build the URL:
let url = 'https://jsonplaceholder.typicode.com/users/' + customerNo
$.ajax({
url: url,
type: 'GET',
dataType: 'json',
data: {
customerNo: customerNo
},
cache: false,
success: function(result) {
if (result.username === 'Antonette') {
// Authorize and go
alert("Authorization success, let's go!");
anchor.data("authorized", true);
goToLink(anchor);
} else {
// Show a message in a alert or div
alert('Not authorized');
}
}
});
// Default to false (Do not process anchor)
return false;
});
HTML:
<ul>
<li><a class="lnkCustomer" href="https://google.com/" target="_blank" data-customerno="1">Google (no go)</a></li>
<li><a class="lnkCustomer" href="https://stackoverflow.com/" target="_blank" data-customerno="2">Stackoverflow (allowed)</a></li>
</ul>

Chrome Back button is not preserving the url history when using Ajax for pagination

pls help me out. i recent used ajax for my laravel pagination. Whenever i click he back button. it does not go back to the page i am coming from. it goes back to page 1. let me Illustrate this clearly.
(1) i have a list of items paginated with jquery ajax.
(2) when i visit the 5th page( for example) and click an item to view details of that item and decided to click the browser back button, i am expected to be taken back to page 5 where i was. instead, i am taken back to page 1.
(3) This is only happening in chrome related browsers. it works well in Firefox;
//BELOW IS MY AJAX CODE;
$(document).ready(function(){
$(document).on('click','.pagination a',function(e){
e.preventDefault();
var pageNumber = $(this).attr('href').split('page=')[1];
getMorePage(pageNumber)
});
function getMorePage(page) {
$.ajax({
url: "/all-products-ajax/"+"?page="+page,
type: "get",
datatype: "html"
}).done(function (data) {
$('#product-view').html(data);
}).fail(function () {
alert('Posts could not be loaded.');
});
}
});
Ajax queries are different than browsing a webpage. You may need to register new routes to browser's history.
https://developer.mozilla.org/en-US/docs/Web/API/History/pushState
You might want to check out here.

AJAX response caching / onclick-event inside of a function

I´m using AJAX to execute some server-side actions and refresh a table inside the page without reloading the page itself. All works fine at first view. But I wrote a function in PHP to send an email and execute it via AJAX. When I´m starting this action for a second time old responses gets triggered.
What exactly happens:
I´m clicking a Button to execute the "Sendmail-Action"
a Modal asks me if I want to execute the action and I´m clicking yes
a PHP-Script gets executed and sends the email
the Modal gets closed after the PHP-Script finishes (~2s)
the table (with emails and so on) gets refreshed and the status updated
What happens next:
I´m clicking a Button to execute the "Sendmail-Action" for the same
or another entry in my table
a Modal asks me if I want to execute the action and I´m clicking yes
the Event triggers twice / 4xAjax-Request instead of 2 (I can see it in my Chrome-Console)
the Modal closes and 2 Mails sended
What I´ve tried to get rid of this behaviour:
checked my JS with JSHint
checked my PHP-Code (no errors in apache error.log)
redesigned the PHP-Script (Sendmail), now the AJAX executes a function
tried different browsers
deactivated AJAX-Caching
completely deactivated Caching with Apache (correct Headers)
deactivated Session-Caching in my php.ini (I don´t use sessions)
unset all variables in PHP
cleared the cache for all of my browsers
checked all headers
searched several hours for solutions
More information about my setup:
jQuery 2.1.4
php 5.4
Apache 2.2
I can´t find a solution to my problem and maybe this is caused because I´m adding the content dynamically to the table. I had the same problem in the past and I´m thinking the Modal (which is also dynamic) triggers the click on the "Yes-Button" twice.
You can put your ajax click handler outside of that function:
$(document).on('click', '.email-resend, .email-send, .show-doc, .show-acc, .more-acc, .no, .yes, .termin', function(){
$.fn.doAction(classname, comEntry);
});
As you mentioned that you have placed this in the function. Instead you should put this outside of it:
$(document).on('click', '.bt-ok', function(){
$.ajax({
....
});
});
Edit by #pandora: Or just use a second function (in my case) like this:
$(document).on('click', '.bt-ok', function(){
$.fn.sendRequest($('#modal').attr('data-1'), $('#modal').attr('data-2'));
});
Then I can call the function like this and execute the AJAX:
$.fn.sendRequest = function(data1, data2) {
$.ajax({
url: 'target.php',
cache: false,
data: { gimme1 : data1, gimme2 : data2 },
success: function(response) {
// Show Error
if(response.length > 0){
alert(response);
}
// Reload Content
$.fn.Reload('','');
// Close Modal
$('#modal').css({'display' : 'none'});
}
});
};

getElementById() ? Remembering the last active tab after a submit / refresh

I have a really annoying problem, that I can't solve since a few days of trying and googlin' around.
I have some tabs in my form.
When I am in the third tab (3 / 3) and I hit submit to update my form I always get to the first tab. I want to stay at the active tab.
Here is my jQuery
$(document).ready(function () {
/***** intra - Tabs *****/
$('.intra-tab-content').hide();
$('.intra-tab-content:first').show();
$('.intra-tab').click(function () {
var tabContentId = '#' + $(this).attr('name');
$('.intra-tab').attr('class', 'intra-tab');
$(this).attr('class', 'intra-tab intra-tab-bar-actual-tab');
$('.intra-tab-content').hide();
$(tabContentId).show();
});
});
And here is my HTML
<div class="intra-tab-bar">
<ul>
<li>foo
</li>
<li>bar
</li>
<li>foobar
</li>
</ul>
Would be great if someone could help me..
Thanks in advance
Krtl
After you hit submit, the default behavior of your page is to reload, thus resulting your page to get into initial state (tab 1 selected).
So there are two opportunities:
You can save the selected tab on your server (e.g. in a session) and load it in jQuery's ready callback
Don't let your page use the default behavior, instead calling your custom submit callback function and stop propagation:
$("#submit-form").submit(function () {
var formData = $(this).serialize(); //jQuery function to get the forms values
$.ajax({
url: "url", //forms url
type: "POST/PUT/GET/DELETE", //default: get
data: formData,
success: function(data) {
//success callback
}
});
return false; //stops propagation
});
There are a bunch of ways to tackle this issue. The most elegant way is already suggested by Florian, instead of using the browser submit functionality, define your own submit behaviour using ajax which prevents a page load.
Alternatively:
If you can utilize local storage i.e., you client is a HTML5
based browser, what you can do is set a flag for which tab you would
like to load the page. Clear the flag after it is used.
Send back an extra parameter to the server with the final tab the user was on. This way when you reload you can have the tab id sent back from the server and reload your page. This combined with ajax will allow you to change tabs on the client to specify server errors too!
Though this answer is just for more ways to solve the problem. For something that just works, go for ajax!

Passing php variables on click without refresh

The problem:
I have a series of 'accept' buttons, on click it opens a lightbox (a modal- using bootstrap), of course this is done without refreshing the page.
On the lightbox I need to show information regarding what is being accepted (therefore I need to pass a PHP variable to the lightbox). So the problem is how can I pass on a variable on click without refreshing the page? I tried using javascript, but the thing is once I set up a variable in JS I can't get that variable to PHP without refreshing the page.
The button has this code.
<button class="btn btn-acceptColor m-t-lg">Accept</button>
The other code isn't relevant for the purpose of this question. I just need the concept of how to actually do it.
Any help!?
there are many examples.
I provides some links, you can use them in your code as you suitability..
1). Ajax Tutorial
2). jQuery Ajax POST example with php
3). jQuery Ajax POST example with php
4). show data in lightbox
5). How to add jquery lightbox to content added to page via ajax?
I hope above links helpful for you
$(".btn-acceptColor").click( function (){
var person = {
name: $("#id-name").val(),
address:$("#id-address").val(),
phone:$("#id-phone").val()
}
$.ajax({
type: "POST",
url: "exaple.php",
data: person,
success: function(msg) {
var msg = $.parseJSON(msg);
if(msg.success=='yes')
{
return true;
// fill you light-box form get value from example.php page
}
else
{
alert('Server error');
return false;
}
}
});
});

Categories

Resources