How to detect tab close in browsers using PHP or Javascript. In other words, How to find if page is refreshed or opened in new tab. I am concerned about tab, not browser.
You can have a listener for the window.onbeforeunload event. You won't be able to detect if the tab is closed from JavaScript, though.
Actually Javascript can tell you if a Tab is going to be closed. Two different methods need to be used (one for IE and one for everyone else).
I wrote a Javascript process to do just what you are asking. Pre-requisites for the process is jQuery and one plugin (livequery - because some of the HTML is dynamically generated after page load). Anyway, here is the js file that does all this (checkclosing.js):
// Global Var
var bodyclicked = false;
var datachanged = false;
var nodirtycheck = false;
// Start the engines :)
$(document).ready(function () {
init();
});
function init() {
bindEvents();
}
function bindEvents() {
// Bind the onClick event for the DOM body
$(document).livequery(function () {
bodyclicked = true;
});
// Bind our event handlers for the change and reset events
$(':input').not('.excludeFromDirtyCheck').bind('change', function () {
if ($(this).hasClass('dataLoader')) {
if (!datachanged) {
return;
}
}
datachanged = true;
$(".hidDataChanged").val("True");
});
$(':reset,:submit').bind('click', function () {
// .NET renders some ASP Buttons as Submit and Reset types
if ($(this).hasClass('notSubmit')) {
return;
}
if ($(this).hasClass('notReset')) {
return;
}
datachanged = false;
$(".hidDataChanged").val("False");
});
// Must have the livequery plugin referenced for this to work
$('.resetchangedform').livequery('click', function (event) {
//alert("resetchanged"); // FIXME
datachanged = false;
// Set our hidden input (on the Administration Master page)
$(".hidDataChanged").val("False");
});
// Must have the livequery plugin referenced for this to work
$('.setchangedform').livequery('click', function (event) {
//alert("setchanged"); // FIXME
datachanged = true;
// Set our hidden input (on the Administration Master page)
$(".hidDataChanged").val("True");
});
// Must have the livequery plugin referenced for this to work
$('.excludeFromDirtyCheck').livequery('click', function (event) {
nodirtycheck = true;
});
// Must have the livequery plugin referenced for this to work
$('.notSubmit').livequery('click', function (event) {
nodirtycheck = true;
});
// Must have the livequery plugin referenced for this to work
$('.dataReloader').livequery('change', function (event) {
nodirtycheck = true;
});
window.onbeforeunload = function () {
//alert("datachanged = " + datachanged + " | nodirtycheck = " + nodirtycheck + " | hidDataChanged = " + $(".hidDataChanged").val());
// Check the hidden textbox
if ($(".hidDataChanged").val() == "True") {
datachanged = true;
}
if (nodirtycheck) {
nodirtycheck = false;
}
else {
if (navigator.appName == "Microsoft Internet Explorer") {
// IE
if (bodyclicked) {
if (datachanged) {
return "You may have unsaved changes...";
}
}
else {
bodyclicked = false;
// Do Nothing
}
}
else {
// Not IE
if (datachanged) {
return "You may have unsaved changes...";
}
else {
// Do Nothing
}
} //if (navigator.appName == "Microsoft Internet Explorer") {
} //window.onbeforeunload = function () {
} // if (nodirtycheck) {
}
Then just include a reference to this file on any page you want to check for a tab close on:
This was built to help prevent users from navigating away from pages with unsaved changes to form values. Yes, I know that most of the time, it is bad practice to prevent the user from closing a tab or navigating away, but in this case - the users requested it and this is an internal application that is not for public consumption.
Any controls that you don't want to be checked for changes prior to letting the user close the tab or navigate away would just be given a class name of excludeFromDirtyCheck.
This may be more than you need, but you can strip off the parts that aren't useful. The basic premise is the same.
Related
I have a long form, that's a sliding page form so that it is broken up into parts for the user.
I do my error checking through jQuery, here is the code:
$("input.next").click(function(e) {
e.preventDefault();
var stage = ((($("#container").position().left) / 950) * -1) + 1;
var thispage = $(this).closest("div.page");
var errors = false;
var isFinal = $(this).hasClass("send");
thispage.find("input.txt").each(function () {
if(($(this).val() == "") && (!$(this).hasClass("optional"))) {
$(this).css("background","#FFE5E5");
errors = true;
} else {
$(this).css("background","#E5FFEA");
}
});
thispage.find(".checkbox").each(function () {
if(!$(this).is(':checked')) errors = true;
});
if(thispage.find("#profileimage").val() == "") errors = true;
thispage.find("textarea.txt").each(function () {
if(($(this).val() == "") && (!$(this).hasClass("optional"))) {
$(this).css("background","#FFE5E5");
errors = true;
} else {
$(this).css("background","#E5FFEA");
}
});
if(!errors) {
// if no errors, slide to next page.
if(!isFinal) {
thispage.find("div.errormessage").fadeOut(50);
$("#container").animate({left: "-=950px"}, 800, function () {
$("ul#stages li").removeClass("active");
$("ul#stages li.stage"+stage).addClass("active");
console.log("Stage: " + stage);
});
}
} else {
thispage.find("div.errormessage").fadeIn(100);
}
console.log("isFinal: " + isFinal);
console.log("Errors: " + errors);
if((isFinal) && (!errors)) {
console.log("submitting form...");
$("#enrolform").submit(); }
});
However when the div.next.send button is pressed, it has a name of sendapplication and in my PHP code I am using:
if(isset($_POST['sendapplication'])) {
..To check whether the entire form was submitted or not. The reason I need to do this is because I also have a 'save' feature of the form, which allows the user to save the data and come back later.
The problem is when the user clicks 'sendapplication' button I don't get that through in the $_POST or $_REQUEST variables. And I think the reason why is because it's the jQuery script that's sending it, and not the button. The button is suppressed because of the e.preventDefault() line.
How can I check that that particular button was pressed? is there someway I can manipulate the .submit() function?
You can add following code into the click() method:
var self= $(this),
form = self.closest(form),
tempElement = $("<input type='hidden'/>");
// clone the important parts of the button used to submit the form.
tempElement
.attr("name", this.name)
.val(self.val())
.appendTo(form);
See jQuery submit() doesn't include submitted button for more details
Anthony Grist's comment is probably a lot better solution to this :)
I am making a view count system. But the problem is that whenever the person reloads the page, the view is incremented.
In order to stop it, I used a session variable.
The code is as follows:
if ($_SESSION['var'] == NULL){
$start = "UPDATE table SET views = views+1 WHERE value = $value";
$_SESSION['var'] = true;
}
If the page is refreshed, the session variable remains intact and the condition fails and nothing happens.
PROBLEM:
But if the page is closed and re-opened, the views don't increase whereas they should.
What am I doing wrong?
I have written session_start() and a PDO query to execute the function.
In order to achieve what you are looking for, you need to destroy session on browser tab/window close. Therefore you need a Ajax request that destroys the session parameter on window close.
Quoting from this article: http://eureka.ykyuen.info/2011/02/22/jquery-javascript-capture-the-browser-or-tab-closed-event/
In your web root, create the js/check_browser_close.js.
/**
* This javascript file checks for the brower/browser tab action.
* It is based on the file menstioned by Daniel Melo.
* Reference: http://stackoverflow.com/questions/1921941/close-kill-the-session-when-the-browser-or-tab-is-closed
*/
var validNavigation = false;
function wireUpEvents() {
/**
* For a list of events that triggers onbeforeunload on IE
* check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
*
* onbeforeunload for IE and chrome
* check http://stackoverflow.com/questions/1802930/setting-onbeforeunload-on-body-element-in-chrome-and-ie-using-jquery
*/
var dont_confirm_leave = 0; //set dont_confirm_leave to 1 when you want the user to be able to leave withou confirmation
var leave_message = 'You sure you want to leave?'
function goodbye(e) {
if (!validNavigation) {
if (dont_confirm_leave!==1) {
if(!e) e = window.event;
//e.cancelBubble is supported by IE - this will kill the bubbling process.
e.cancelBubble = true;
e.returnValue = leave_message;
//e.stopPropagation works in Firefox.
if (e.stopPropagation) {
e.stopPropagation();
e.preventDefault();
}
//return works for Chrome and Safari
return leave_message;
}
}
}
window.onbeforeunload=goodbye;
// Attach the event keypress to exclude the F5 refresh
$(document).bind('keypress', function(e) {
if (e.keyCode == 116){
validNavigation = true;
}
});
// Attach the event click for all links in the page
$("a").bind("click", function() {
validNavigation = true;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function() {
validNavigation = true;
});
// Attach the event click for all inputs in the page
$("input[type=submit]").bind("click", function() {
validNavigation = true;
});
}
// Wire up the events as soon as the DOM tree is ready
$(document).ready(function() {
wireUpEvents();
});
Also create the following .html in your web root to test the above Javascript file.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" src="js/check_browser_close.js"></script>
</head>
<body>
<h1>Eureka!</h1>
Google
Yahoo
Eureka!
</body>
</html>
Now you need to modify the code to call you server side file to destroy the session using Ajax.
I know that this is impossible via PHP supervars, but see this website:
When we navigate on the pages, the title and meta just changes and this affect the facebook too, see:
How he is doing it? I have a ajax navigation system too, and need to set og, but I don't know how to do dinamically as he did.
Just a comment, he have hidden INPUTS with values of the meta:
But I still don't know how he can parse this before the website being rendered.
The URL fragment is NEVER sent to the server. It is used as a reference by the browser. "Traditionally" it is used to scroll to an element with the ID referenced by the fragment, however more recently it has been given some more exotic uses.
In particular, #! is a shebang, and has the meaning that "this page is being loaded by AJAX, but if you load the following relative to the domain, you will get the full page anyway" - this is particularly useful for search engines.
Basically, use AJAX combined with location.hash to get it to work.
it's just some js(jQuery)
<script type="text/javascript">
var current_page = '';
$("a").live("click", function(){
return change_hash(this,1);
});
function change_hash(el,type) {
if(type==1) {
var link = $(el).attr("href");
}
else
{
var link = el;
}
var link_ar = link.split('/#!');
if(link_ar[1]!=undefined) {
if((link_ar[1].length>3)&&(link_ar[1].substr(0,1)=='/')) {
window.location.hash = '#!'+link_ar[1];
return false;
}
else
{
return true;
}
}
else
{
return true;
}
return false;
}
$(function(){
$(window).hashchange( function(){
address = location.hash.replace("#!","");
var skip=false;
if((address.substr(0,1)=='/')&&(address!=current_page)) {
$("#content").html('<div class="content-box"><div class="ajax-loading">carregando...</div></div>');
$("html, body").animate({ scrollTop: 0 }, "slow");
if (address.indexOf(".php") == -1) {
var newaddress = address.replace(/[^a-zA-Z0-9_\.]+/g,"");
if('/'+newaddress!=address) { change_hash('/#!/'+newaddress,2);skip=true; }
address='/PerfilDetalhe.php?user='+newaddress;
}
if(skip==false) {
$.get('http://www.suamusica.com.br'+address, function(htmldata) {
$("#content").html(htmldata);
document.title = $('#metaTitle').val();
$('meta[name=description]').attr('content', $('#metaDescr').val());
$('meta[name=keywords]').attr('content', $('#metaKeywords').val());
$('meta[property="og\\:description"]').attr('content', $('#metaDescr').val());
$('meta[property=og\\:title]').attr('content', $('#metaTitle').val());
$('meta[property=og\\:url]').attr('content', $('#metaURL').val());
$('meta[property=og\\:image]').attr('content', $('#metaImage').val());
$('meta[property=og\\:type]').attr('content', $('#metaType').val());
$('meta[name=DC\\.title]').attr('content', $('#metaTitle').val());
$('meta[name=DC\\.description]').attr('content', $('#metaDescr').val());
$('meta[name=DC\\.subject]').attr('content', $('#metaKeywords').val());
}).fail(function() { $("#content").html('<div class="content-box error-box"><h1>Ooops!</h1><p>A página acessada não existe ou não foi encontrada.</p></div>'); });
current_page = address;
}
$.get('http://www.suamusica.com.br/msg_check.php', function(resp) {
if(resp==1) {
$('#msg-notify').show();
}
else $('#msg-notify').hide();
})
$('.tipsy-s').remove();
}
});
var loc_h_n = window.location.hash.replace("#", "").replace("!", "").replace(".do", ".php")
if(window.location.hash!='#!'+loc_h_n&&window.location.hash!='') {
window.location.hash = '#!'+loc_h_n;
}
$(window).hashchange();
});
</script>
as you can see he returns false on clicks and acts based on the hashtag value
I have a jQuery script that dynamically changes select menus. The script uses the function populate() everytime a change event occurs in one of the menus. I would like the same script to run after a form submit. To have an idea this is what the script looks like...
$(document).ready(function(){
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
function populate() {
if ($('#STATEID').val() == 'AK' || $('#OB_USTATEID').val() == 'DC') {
// Alaska and District Columbia have no counties
$('#county_drop_down3').hide();
$('#no_county_drop_down3').show();
}
else {
fetch.doPost('../../getCounties2c.php');
}
}
$('#STATEID').change(populate);
var fetch = function() {
var counties = $('#countyid');
return {
doPost: function(src) {
$('#loading_county_drop_down3').show(); // Show the Loading...
$('#county_drop_down3').hide(); // Hide the drop down
$('#no_county_drop_down3').hide(); // Hide the "no counties" message (if it's the case)
if (src)
$.post(src, { state_code3: $('#STATEID').val() }, this.getCounties);
else
throw new Error('No SRC was passed to getCounties!');
},
getCounties: function(results) {
if (!results)
return;
var allCities = $("<option value=\"All\">All Counties</option>");
counties.html(results);
counties.prepend(allCities);
var first = getUrlVars()["countyid"];
if (first) {
counties.val(first).attr('selected',true);
}
else {
counties.val("All").attr('selected',true);
}
$('#loading_county_drop_down3').hide(); // Hide the Loading...
$('#county_drop_down3').show(); // Show the drop down
}
}
}();
populate();
});
How can I accomplish that? Any suggestions will be highly appreciated!
Use $(element).submit(function (e) {} ); to catch a submit event. You can even fire it off, by calling $(element).submit().
jQuery docs : http://api.jquery.com/submit/
I'm loading external php pages through ajax. The external pages consists of jquery based image slider. It doesn't get loaded. Here I call the page through Ajax.
Load Jquery
it gets loaded but the navigating functions within that page doesn't work.
here is the ajax navigation which is called
var please_wait = null;
function open_url(url, target) {
if (!document.getElementById) {
return false;
}
if (please_wait != null) {
document.getElementById("target").innerHTML = please_wait;
}
if (window.ActiveXObject) {
link = new ActiveXObject("Microsoft.XMLHTTP");
} else if (window.XMLHttpRequest) {
link = new XMLHttpRequest();
}
if (link == undefined) {
return false;
}
link.onreadystatechange = function() {
response(url, target);
}
link.open("GET", url, true);
link.send(null);
}
function response(url, target) {
if (link.readyState == 4) {
document.getElementById(target).innerHTML = (link.status == 200) ? link.responseText : "Ooops!! A broken link! Please contact the webmaster of this website ASAP and give him the fallowing errorcode: " + link.status;
}
}
function set_loading_message(msg) {
please_wait = '<img src="images/ajax-loader.gif"/>';
}
Where do I make the correction to make it work with my Jquery based page.