Startup JavaScript code is not executed when using the Firefox "Back" button - javascript

This website has a fancy effect: when a navigation link is clicked, the content fades out and when the new page (on a different URL) loads, its contents fade in.
What's interesting is, after users click on the "Back" button of their browsers, they go back to the previous page and the content still fades in. In other words, the previous page doesn't stay at the faded-out state, which is what was last seen. According to this comment, a page should be staying at its last seen state.
I tried many ways to reproduce this effect, yet on my tests, after clicking on the "Back" button the previous page still shows nothing (the content stays at the faded-out state). Sometimes it works on some browsers but not on others. Sometimes it works, but then it doesn't after reopening the browser.
How does the website implement this effect, which even works after users use the "Back" button to go to the previous page?
=== EDIT 1 ===
Here are my test pages.
=== EDIT 2 ===
The above test pages have been tested with Firefox on three different PCs, and Firefox from version 4 all the way to version 20 via an online cross-browser testing service. And the results are the same: doesn't work.

You need a very simple workaround: hook into window.unload event, and a specific condition to reload the page inside window.onpageshow!
Firefox fix
jQuery:
$(window).unload(function () { $(window).unbind('unload'); });
JavaScript:
function UnloadHandler() { window.removeEventListener('unload', UnloadHandler, false); }
window.addEventListener('unload', UnloadHandler, false);
iOS Safari fix
jQuery:
$(window).bind('pageshow', function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
JavaScript:
window.addEventListener('pageshow', function (event) {
if (event.persisted) {
window.location.reload()
}
}, false);
Working sample
Since I don't have access to update your page, I've uploaded one here.
Why Firefox needs window.onunload? MDN window.unload says:
Using this event handler in your page prevents Firefox 1.5 from caching the page in the in-memory bfcache. See Using Firefox 1.5 caching for details.
Some users might not want to disable Firefox's bfcache [see section Page caching despite unload and beforeunload handlers), and it is why the Firefox fix above is unbinding the onunload event inside of the onunload event.
Why Safari needs window.onpageshow? Apparently there's no way of disabling Safari's "bfcache", and we must refresh the page when it's shown.
PS. bfcache means back/forward cache.
Full HTML/JavaScript for reference:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<div>
Page 1
Page 2
</div>
<div id="content">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas laoreet imperdiet diam, in sodales velit porta eget. Ut tellus urna, vestibulum vel facilisis eu, blandit sed est. Sed tortor justo, interdum vel iaculis eu, semper ut libero. Morbi porttitor sem eget dolor eleifend fermentum. Mauris lacinia dictum lacus ut pharetra. Proin lacus felis, vestibulum sit amet malesuada id, pretium at lorem. Duis elementum sapien vitae nibh consequat tincidunt. Proin gravida rhoncus metus sed feugiat. Sed ultricies tellus et augue adipiscing dictum. In vitae tellus eget sapien fringilla tincidunt. Vestibulum gravida, velit quis mattis elementum, lacus felis vestibulum neque, et commodo quam orci quis odio. Nunc varius viverra metus, eu dictum massa venenatis vel. Cras suscipit, orci a gravida pretium, erat massa facilisis turpis, quis sodales sem metus vitae ligula. Nunc interdum augue vel arcu vulputate quis aliquet nulla vehicula. Suspendisse eros odio, ultrices hendrerit euismod nec, condimentum sed metus.</p>
<p>Donec at dolor et arcu aliquam tincidunt. Nulla eu elit sit amet leo facilisis posuere. Etiam non elit ac elit ornare elementum a vitae felis. Aenean semper nunc urna. Ut et interdum mi. Duis mollis est eu leo gravida vitae adipiscing leo commodo. Ut scelerisque cursus nulla, nec bibendum elit molestie sed. Nulla facilisi. Proin neque arcu, aliquam sed sagittis non, ultrices in enim. Fusce vitae nunc neque, ut sodales magna. Proin aliquam lobortis augue sed aliquet. Maecenas sit amet pellentesque mauris. Donec luctus purus hendrerit nisl pharetra eleifend. Mauris a lectus mi. In elit dui, porta a venenatis vel, consectetur id magna. Quisque vehicula leo vel nulla convallis quis sollicitudin sem fringilla.</p>
<p>Morbi nec mi odio, eget porttitor nisi. Duis luctus blandit lacus. Donec quis sagittis mi. Maecenas id nisl enim. Aliquam erat volutpat. Nulla facilisi. Donec ac velit diam, interdum rutrum mauris. Nullam at odio eget felis tempus elementum. Nam a augue nibh, sed bibendum massa. Vivamus eget sollicitudin mauris. Pellentesque dapibus quam nec ligula blandit scelerisque. In vulputate mauris vel dolor interdum vitae aliquet nisl convallis. In massa mi, consectetur id malesuada at, suscipit vitae libero. Sed a ligula erat.</p>
</div>
<script type="text/javascript">
$(function() {
$('body').hide().fadeIn(800);
$('a').click(function() {
var href = $(this).attr('href');
$('body').fadeOut(800, function() {
window.location = href;
});
return false;
});
});
// Firefox fix
$(window).unload(function () { $(window).unbind('unload'); });
// iOS Safari fix
$(window).bind('pageshow', function(event) {
if (event.originalEvent.persisted) {
window.location.reload()
}
});
</script>
</body>
</html>

For anybody running in problems with Rails and this -- your issue isn't bfcache -- it's the turbolinks gem. Here is how to remove it.

Maybe that's not not exactly what you are asking, but they achive the effect in this way: page content starts hidden.
That's always, even when you click back button, because content hidden is declared in a style or class in markup.
Then there's javascript code that fadeIn the content after the ready event:
$('#content').fadeIn(800);

Related

Edit webpage with javascript trick - how to "unedit"?

I can use the following scriptlet to make a webpage editable
javascript:document.body.contentEditable='true'; document.designMode='on'; void 0
but after doing the edits I want to do (e.g., for a screenshot for a manual), how do I restore the state of the page to its normal uneditable state? I have tried changing true and 0 to false and 1 respectively, to no avail.
You would be able to leave edit mode by changing your command to the following
javascript:document.body.contentEditable='false'; document.designMode='off'; void 0
I have updated my answer to include a simple working example of my answer, tested in chrome, safari and firefox.
<input type="button" value="Edit" onclick="javascript:document.body.contentEditable='true'; document.designMode='on'; void 0"> <input type="button" value="Disable Edit" onclick="javascript:document.body.contentEditable='false'; document.designMode='off'; void 0">
<div><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel arcu eget risus iaculis imperdiet vel in leo. Pellentesque commodo nibh tellus. Morbi ultricies consectetur fermentum. Aenean eu vehicula libero. Nam pellentesque lobortis dui, ut rutrum neque suscipit at. In tincidunt justo sit amet faucibus bibendum. Sed viverra dignissim nulla, ac lacinia orci bibendum at.</p><p>Mauris enim ex, mattis et augue nec, maximus dignissim leo. Donec maximus interdum blandit. Phasellus porta accumsan est, ac sagittis arcu sollicitudin quis. Donec consequat velit at congue congue. Suspendisse feugiat molestie neque, id condimentum tellus. Vestibulum fringilla libero nec iaculis pellentesque. Cras mollis risus eros, eget mollis augue molestie ac. Nulla tincidunt metus at pulvinar cursus.</p></div>
You need to remove the contenteditable attribute.
var demo_editable = document.getElementById('demo-editable');
var demo_button = document.getElementById('demo-button');
demo_editable.setAttribute('contenteditable',true);
demo_button.onclick = function() {
delete demo_editable.removeAttribute('contenteditable');
}
<div id="demo-editable">This is editable</div><button id="demo-button">Make not editable</button>
Or you can set the attribute to false.
var demo_editable = document.getElementById('demo-editable');
var demo_button = document.getElementById('demo-button');
demo_editable.setAttribute('contenteditable',true);
demo_button.onclick = function() {
delete demo_editable.setAttribute('contenteditable',false);
}
<div id="demo-editable">This is editable</div><button id="demo-button">Make not editable</button>
Try this:
Hit F12 to inspect the page
Right-click on the top-most element the <html> tag
From the resulting contextmenu, select "Edit as HTML"
Focus the editable HTML and hit Ctrl+A to select all
Hit Ctrl+C to copy the page's HTML to your clipboard
Make the edits to the contenteditable section
Repeat steps 1 through 4
Ctrl+V to paste over the edited HTML with the page's original HTML

JQuery UI Tab selecetion not working properly

I am trying to implement JQuery Tabs on my page. But, the problem is, when I click on the tabs,the UI of the tabs do not change.The selected tab always remains selected and the unselected tab is always unselected. I am not able to figure out which tab is actually clicked.Since, I have used "bind" to bind the click event on the tabs,the implementation is working as expected.Since I am totally new to JQuery UI stuff, I am not able to figure out where I am going wrong.
Here is the jsp code for the tabs(written as mentioned on the net).
<div id="tabs" style="margin-top: 100px; width: 100%;margin-left:20%;">
<ul>
<li id="allocated">Allocated</li>
<li id="pending">Pending</li>
</ul>
</div>
In javascript file :
$('#tabs',container).tabs();
I have written different bind event for both the tabs as follows :
$("#allocated", container).unbind("click").click(function() {
});
$("#pending", container).unbind("click").click(function() {
});
Do I need to change the state of the tabs manually or it should change by itself.
There is no content to display for your tabs, that's why this is not working properly :
<div id="tabs" style="margin-top: 100px; width: 100%;margin-left:20%;">
<ul>
<li id="allocated">Allocated
</li>
<li id="pending">Pending
</li>
</ul>
<div id="tabs-1">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus. Curabitur nec arcu. Donec sollicitudin mi sit amet mauris. Nam elementum quam ullamcorper ante. Etiam aliquet massa et lorem. Mauris dapibus lacus auctor risus. Aenean tempor ullamcorper leo. Vivamus sed magna quis ligula eleifend adipiscing. Duis orci. Aliquam sodales tortor vitae ipsum. Aliquam nulla. Duis aliquam molestie erat. Ut et mauris vel pede varius sollicitudin. Sed ut dolor nec orci tincidunt interdum. Phasellus ipsum. Nunc tristique tempus lectus.</p>
</div>
<div id="tabs-2">
<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus gravida ante, ut pharetra massa metus id nunc. Duis scelerisque molestie turpis. Sed fringilla, massa eget luctus malesuada, metus eros molestie lectus, ut tempus eros massa ut dolor. Aenean aliquet fringilla sem. Suspendisse sed ligula in ligula suscipit aliquam. Praesent in eros vestibulum mi adipiscing adipiscing. Morbi facilisis. Curabitur ornare consequat nunc. Aenean vel metus. Ut posuere viverra nulla. Aliquam erat volutpat. Pellentesque convallis. Maecenas feugiat, tellus pellentesque pretium posuere, felis lorem euismod felis, eu ornare leo nisi vel felis. Mauris consectetur tortor et purus.</p>
</div>
</div>
And no need to specify container in your selector :
$('#tabs').tabs();
» Live Demo
Why you are unbinding the click event? This will stop the click event added by $('#tabs').tabs();.
If you want to do custom actions on the click, you just need to define the click:
$("#allocated", container).click(function() {
alert(1);
});
$("#pending", container).click(function() {
alert(2)
});

Make the contents of a <details> tag animate when open with jQuery/JS

I simply want the contents of the HTML5 details tag to 'glide'/animate open rather than just pop open/appear instantly. Is this possible with jQuery/Javascript?
Fiddle
HTML:
<details>
<summary>Show/Hide</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum laoreet metus auctor tempor dignissim. Nunc tempor ligula malesuada, adipiscing justo quis, ultrices libero. Curabitur pretium odio sagittis lorem euismod, a ultrices sem ultrices. Integer sapien nibh, mollis id pretium id, dignissim ut dui. Nam sit amet lectus lectus. Cras scelerisque risus a dui accumsan, in dignissim dolor sodales. Nunc aliquam pharetra dui, a consectetur velit lobortis vel.</p>
<p>Mauris convallis orci in semper aliquam. Ut mollis laoreet nibh pretium tincidunt. Donec aliquam at odio sit amet dictum. Phasellus sapien leo, feugiat sit amet sagittis in, congue vel lectus. Donec elementum est vitae nulla interdum laoreet. Curabitur fringilla a tellus non laoreet. Aliquam vel lectus convallis massa pulvinar pellentesque. Mauris laoreet pharetra turpis vel tristique. Sed ligula ligula, sodales sed auctor in, aliquam sit amet lorem. Etiam vestibulum, libero vel dignissim ultrices, lacus mauris lacinia enim, quis aliquam nibh mauris eu mauris. Etiam sapien leo, dapibus et libero sed, laoreet ornare tellus.</p>
<p>Sed placerat vehicula magna et adipiscing. Nam euismod nibh ut tellus tempor, eget lobortis metus iaculis. In laoreet, enim in dignissim pellentesque, felis augue tincidunt massa, vestibulum fringilla mauris sapien in diam. Duis interdum molestie fermentum. Aenean dictum varius augue, id luctus neque viverra id. Nam eleifend tempus mauris in mattis. Sed id risus non magna semper blandit in vel arcu. Suspendisse quis nisi ligula. Fusce vestibulum at enim eu.</p>
</details>
Too bad a simple CSS transition can't be used.
I'd therefore suggest wrapping the sibling elements of the summary element and then using .slideToggle() on them. It isn't that simple though, you need to add the open attribute to details, and hide the inner wrapped elements by default.
This only works if you use e.preventDefault() to prevent the default functionality; however, you then need to rewrite the arrow indicators, (►,▼).
You would use summary::-webkit-details-marker and display:none to remove the marker that is no longer working, and add your own custom markers via the :before/:after pseudo elements.
UPDATED EXAMPLE HERE
$('details summary').each(function(){
$(this).nextAll().wrapAll('<div id="wrap"></div>');
});
$('details').attr('open','').find('#wrap').css('display','none');
$('details summary').click(function(e) {
e.preventDefault();
$(this).siblings('div#wrap').slideToggle(function(){
$(this).parent('details').toggleClass('open');
});
});
CSS:
summary::-webkit-details-marker {
display: none;
}
summary:before {
content: "►";
}
details.open summary:before {
content: "▼";
}
If you want the details element to be open by default, add class="open" as opposed to the attribute open, and then use this: $('details.open div#wrap').css('display','block');
ALTERNATIVE EXAMPLE - (open by default)
Based on #JoshCrozier's answer, I've made a solution that uses the open attribute instead of the extra open class. This way you don't have to change the css.
If you would like to use css to change the appearance of the <details> element, you can use the same style rules regardless of whether the browser supports the <details> element, and regardless of whether javascript is enabled in the browser, since you only have to consider the open attribute, and no special classes.
In addition, there is no special id on the wrapper element, making the solution slightly more robust and generic.
Also, this solutions takes <details> elements that should be open by default into account.
$('details summary').each(function() {
var $Wrapper = $(this).nextAll().wrapAll('<div></div>').parent();
// Hide elements that are not open by default
if(!$(this).parent('details').attr('open'))
$Wrapper.hide();
$(this).click(function(Event) {
Event.preventDefault();
if($(this).parent('details').attr('open')) {
$Wrapper.slideUp(function() {
// Remove the open attribute after sliding so, so the animation is visible in browsers supporting the <details> element
$(this).parent('details').removeAttr('open');
});
} else {
// Add the open attribute before sliding down, so the animation is visible in browsers supporting the <details> element
$(this).parent('details').attr('open', true);
$Wrapper.slideDown();
}
});
});

jQuery columnize crashes when setting height

I'm using the jquery columnizer plugin to create columns of a text in a div. The used plugin can be found here.
Below is an example of my html which should be divided into three columns:
<div class="textColumn">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum adipiscing,
nisi tempus tincidunt tempor, lorem libero venenatis lectus, molestie congue arcu risus ut
lorem. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras mauris lorem, eleifend
vitae auctor id, rhoncus eget mi. Nunc convallis condimentum pretium. Praesent vulputate
mauris sit amet nisl porttitor fringilla. Aliquam sit amet venenatis risus. Nullam
malesuada hendrerit dolor, id sagittis libero condimentum non. Sed dapibus bibendum augue,
id lobortis arcu iaculis laoreet. Maecenas lacinia mattis ipsum, ut vehicula nulla
tristique id. Quisque vehicula orci vitae nibh ultricies ac dictum metus pretium. Donec id
arcu tellus, vulputate blandit augue. Integer turpis felis, cursus et congue sit amet,
mollis at neque. Nunc pellentesque erat vel odio tempus aliquam.<br>
<br>
Quisque faucibus lectus luctus odio blandit aliquet. Phasellus blandit augue vel eros
lacinia nec hendrerit ligula sagittis. Sed sollicitudin ultricies sem sit ametpellentesque.
Fusce semper purus vel massa porttitor vestibulum. Fusce eget erat eu augue ullamcorper
mattis. Morbi adipiscing fermentum purus, ut ultrices libero tristique sed. Fusce ut augue
in ante rhoncus iaculis. Nunc auctor, est sit amet ornare dictum, dolor odio elementum
orci, vitae porta enim nisi id felis. Aenean justo mauris, fringilla id faucibus eget,
tincidunt ornare purus. Aenean dapibus sapien non justo elementum sollicitudin. In at
vehicula turpis. Sed porta rhoncus arcu a cursus. Maecenas eu purus in urna mattis ornare
et et arcu. Suspendisse auctor magna ac tortor condimentum condimentum.<br>
</div>
</div>
In a generic javascript file i've defined a document.ready function in which in executing the columnizer to create my columns. This is done with the javascript below. It works fine when defining only a width. However, I also want to set a limited height for the columns. As soon as I do this the plugin (and there with also the browser) crashes.
$(document).ready(function(){
$('#content.one .textColumn .text').columnize({
width: 169
/*,height: 162*/ /*Enabling this rule crashes the internet!*/
});
});
I've tried with the width and height both setup, but also with only the height setup. Both make the plugin crash. Also defining the height inside the plugin (and therewith modifying the plugin) make it crash. According to this jquery plugin page it should be possible to set a height and also this example shows a working version.
Does anyone have a good resolution to this?
It is a bug in the plugin, please use this one:
https://raw.github.com/cioddi/Columnizer-jQuery-Plugin/71eae2c531419274a1ec085f6a6485038e98c9f3/src/jquery.columnizer.js
I got it from a git push request. Your js code is valid. please see this jsfiddle as prove:
http://jsfiddle.net/kxMJM/
I got the patched plugin from cioddi

resize textbox automatically according to the content

http://jsfiddle.net/h2vMN/1/
I have a text box text inside it already, in the actual application this will be filled dynamically, but for the sake of this question it has been pre filled.
<textarea id="textarea">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tempor commodo ornare. Donec lobortis dui sed lectus egestas tristique. Vivamus vel metus turpis, faucibus varius risus. Aenean ante mauris, ultrices id facilisis vitae, dignissim eget sem. Quisque sed justo lectus, eget aliquet leo. Curabitur in mauris et diam fermentum venenatis. Proin ullamcorper, neque a vehicula euismod, odio enim aliquam ipsum, eu tristique urna sapien nec erat.
Aliquam erat volutpat. In in lacus cursus dolor pellentesque posuere. Cras eu metus urna, a rhoncus ligula. Ut hendrerit orci in arcu dignissim id fermentum orci vulputate. Sed ante ligula, volutpat eu convallis vel, auctor in metus. Mauris euismod, metus eget venenatis sodales, risus tellus volutpat elit, et aliquet massa tellus ut sapien. Mauris tempor posuere massa et consectetur. Duis dignissim enim a nulla ultricies vitae vulputate felis commodo. Phasellus mollis est eget odio porttitor consequat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus ut nibh auctor libero sagittis semper vitae quis erat.
</textarea>​
When I run the above code, it shows a tiny text area with scroll bars all over it. In other words, completely useless in terms of being user friendly. How do I automatically resize the text box according to the amount of content their is and it has a set width of 600px.
#textarea{width:600px;}​
I would like a javascript/jquery solution.
I have tried the .autoresize solution unsuccessfully, which can be found here:
http://james.padolsey.com/demos/plugins/jQuery/autoresize.jquery.js/view
Note, the height should be resized automatically
Thy this:
$(document).ready(function(){
tx = $('#textarea')
tx.height(tx.prop('scrollHeight'));
})
DEMO
$(document).ready(function(){
var heightFudgeFactor = 10;
var id = 'tempid' + Date.now();
$('#textarea').after( $('<div>').css('font-family','monospace').css('white-space','pre-wrap').css('word-wrap','break-word').attr('id',id).css('width',$('#textarea').width()).text( $('#textarea').text() ) );
$('#textarea').css('height',$('#'+id).outerHeight() + heightFudgeFactor).next().remove();
});​
Here's one way of doing it, I'm creating a secondary div that's the height of the textarea, based on content, but you'll need to play with it a little more to get it to your actual liking
I once used this plugin: http://www.jacklmoore.com/autosize
It worked fine.

Categories

Resources