Basically it breaks down like this:
- A master template page is loaded when one visits the application.
- Links are handled by an onclick handler, which reload relevant portions of the master via a jQuery ajax call, trigger other events, etc.
- After the initial onclick handler completes, it then calls two or more ajax callbacks which update other portions of the page.
The problem:
- The final callback reads CakePHP's flash message command $session->flash(), and displays the result in a simple javascript popup, who's div tag is created via $('body').prepend(). Once the popup is closed, the element that was created is .remove()'ed from the DOM.
- When the user clicks a link and the flash message callback is ran for the next page, the CakePHP flash message data never got deleted, and it redisplays the message. This will repeat anywhere from 2-5 times as one continues to click pages, or until a little time has passed, and then finally delete the message from the PHP session.
- When visiting the ajax link directly, the flash data is displayed once, and then deleted after the page is reloaded.
This has been boggling my mind for the last week. I've trimmed out every other unrelated thing except the callback itself, and it still displays the same behavior. Frustrating.
The code is quite simple, and looks like so:
The layout page which gets handed back after an onclick call.
<?php echo $content_for_layout ?>
<script>
$(window).ready(function() {
page_load_callback();
});
</script>
The javascript.
function page_load_callback() {
$.ajaxSetup({
cache: true // We want our client to cache stuff, and override this in PHP.
});
$.ajax({
cache: false, // Force this to not cache via jQuery
beforeSend: function() {
$('body').prepend('<div id="flash_message_popup"></div>');
},
url: flash_message_popup_link, // global variable set in default.ctp
success: function(data) {
$('#flash_message_popup').html(data);
if ($('#flash_message_popup').is(':empty')) {
$('#flash_message_popup').remove();
} else {
create_popup('flash_message_popup');
}
},
error: function(a, b, c) {
$('#flash_message_popup').remove();
}
});
}
function create_popup(tag) {
if (editing_hall == true) {
return false;
}
var selector = '#' + tag;
$(selector).attr('style', 'position: absolute; display: none; top: 5; left: 5; z-index: 100;');
$(selector).slideDown('slow');
}
The *.ctp file.
<?php if ($message = $session->flash()): ?>
<span id="flash_data">
<div class="flash_message"><?php echo $message; ?></div>
<div class="btn_large bottom_round"><a name="" onclick="$('#flash_message_popup').slideUp('slow', function() { $('#flash_message_popup').remove(); });">close</a></div>
</span>
<?php endif; ?>
The controller method.
function flash_message_popup() {
$expires = 60*60*24*30*7;
header('Expires: '.gmdate('D, d M Y H:i:s', time()-$expires) . ' JST'); // minus for past
$this->layout = 'ajax';
$this->render('../elements/flash_message_popup');
}
Sessions get stored in a database, and haven't proven to be a problem up until this specific instance. I'm not sure if this is a browser caching problem (I shouldn't be? I am specifically not caching via both PHP and jQuery), a quirky session problem, a timing issue, something going haywire in my javascript, or what. I've tried adding a redundant callback which deletes the session in question with $this->Session->delete('Messages.flash'); with no luck as well.
If anyone has any advice I'd love to hear it. I am plum out of ideas.
Edit: I've also checked the Apache logs, and the callback is definitely getting called by the ajax query, but not deleting the session message. Only after I manually call it does it delete.