Browser back button with divs hidden with css - javascript

I have a website where real estate properties search results are displayed like using <div>s with just 6 displayed by default and "load more" button. When user clicks Load more button, 9 more posts displayed, etc. How it is done: divs are hidden by default (display: none;) and then .show class is added to the next 9 items.
a("span.more-search-items").on("click", function(t) {
t.preventDefault();
var e = a(this).parents(".property-search");
e.find(".prop").not(".show").slice(0, 9).each(function() {
var t = a(this).attr("data-img");
a(this).css("background-image", "url(" + t + ")"), a(this).find(".main-image").attr("src", t), a(this).addClass("show")
}), 0 == e.find(".prop").not(".show").length && a("span.more-search-items").hide();
e.find(".prop.show").length
When user goes to single property and then hits back browser button, it shows the first 6 items again. I tried to implement history.pushState() method there where URL changes for each "load more" button click:
var href = window.location.href.replace(window.location.hash, '');
var currentPage = location.hash.replace("#","");
history.pushState(null, null, href + "#" + (+currentPage + 1));
URL changes but the story is still the same - only first 6 results are being displayed when user goes back in history. Is there something I can do in this situation?

If you need to deal with History API you need
on load more click you need to push or replace the history with something like the numbers of visible divs with hash #15 , #24 something like this
With push/replace state you need to use $(window).on('popstate' , function(){ alert(window.location.hash); }) and while user goes to single property it refresh all the page and when browser back button clicked it returns and refreshes the previous page .. so you need to check alert(window.location.hash); when page load
Finally when you got an alert with the number from window.location.hash you can then show the divs depending on it
Ok let me explain this for you in code
$(document).ready(function(){
alert(window.location.hash); // check the alert here
$('.load_more_button').on('click' , function(){
if(window.location.hash){
var href = window.location.href.split('#');
var currentPage = parseInt(window.location.hash);
history.pushState(null, null, href[0] + "#" + (+currentPage + 1));
}
});
$(window).on('popstate' , function(){
alert(window.location.hash); // check the alert here
});
});
You can start from here when you get the number do as you like

Related

Replace a "Click to load more" into a Scroll to load more

Currently, my client's website has a "Load more" button, linked to the Shutterstock API to load more photos everytime you click on that button.
My client asked to change this into "When the user scrolls down, it loads automatically more images".
So what I thought, since I'm not an experienced coder, is to add a function linked with window.scroll that would trigger a click on that button once you reach the top of that button, using the following code:
$(window).scroll(function() {
var top_of_element = $("#load_more_images").offset().top;
var bottom_of_element = $("#load_more_images").offset().top + $("#load_more_images").outerHeight();
var bottom_of_screen = $(window).scrollTop() + window.innerHeight;
var top_of_screen = $(window).scrollTop();
if((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)){
$("#load_more_images").trigger("click");
}
else {
// The element is not visible, do something else
}
});
The issue, is that once the button is in view, it triggers the click multiple time, and it loads the next 6 images multiple times back to back. I guess it's clicking multiple time since the button stays in view, not sure how to handle this.
The code for the "load more" function that works linked to that "load_more_images" button is in a "func.php" page (it's for a Wordpress site, and it's in a plugin) :
jQuery("#load_more_images").click(function() {
jQuery(this).hide();
jQuery(".load_more_wrapper .loader").show();
var ajax_url = "'.admin_url('admin-ajax.php').'";
jQuery.post(
ajax_url,
{
"action": "pd_load_more_img",
"data": {
"type": search_type,
"page":page+1,
"image_type": "'.(isset($_GET["image_type"]) ? $_GET["image_type"] : "all").'"';
if (isset($_GET['category'])){
$js.=',
"category":'.$_GET['category'];
}
if (isset($_GET['search'])){
$js.=',
"search":"'.$_GET['search'].'"';
}
$js.= '}
},
function(data){
page++;
jQuery("#images_container").append(data);
jQuery(".load_more_wrapper .loader").hide();
jQuery("#load_more_images").show();
jQuery(".category-link").dotdotdot();
}
);
});';
Any idea how I could make this work? All I need is to activate that existant function that is currently bound to a click event, but on scroll, when I reach that button, or a certain element in the page at the bottom.
Thanks a lot
You can use that function instead of your click function:-
$(window).scroll( function(e){ if($(window).scrollTop()>= jQuery('#load_more_images').position().top){ doYourFunctionHere(); } }

trigger functions no longer working after implement ajax scroll pagination

I have developed an audio platform similar to Soundcloud and it all works(ed) perfectly! Until I decided to create an Ajax scroll pagination.
Both the pagination and Ajax work fine. However, I have noticed some JavaScript that used to work before implementing Ajax, which no longer does.
The script has a pretty simple duty; play a track when the user clicks the play button (or pause when the user clicks on it again). Then, once the track has finished, move on to the next track until it finally reaches the end.
What happens now is, when the page first loads up (along with the 10 tracks that load with the page), the script will work as it is supposed to. But, when the user scrolls down to get more results to load, if the user clicks on one of the newly loaded tracks play button, the track either won't play, or it will play over the other track which is supposed to pause (and then all the buttons just completely stop working).
Here is all of the feed.js (removed as much bloat code as possible, and placed comments):
$(document).ready(function(){ // on page load
var tp = 1; // set track page equal to one
loadTracks(tp); // then load all of the tracks
jQuery(function($) {
$('.f-outer-container').on('scroll', function() { // when the user scrolls to the bottom of the page load more tracks
if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
tp++;
loadTracks(tp);
}
});
});
function loadTracks(track_page){
$.post('/spectrum-rr/core/_func/functions/loadTrack.php', {'page': tp}, function(data){ // get send and get data from loadTrack.php
$("#f-ap__aj").append(data); // append those tracks in the feed
// player functions
$(".track-w__trigger").click(function(){ // when the play button is clicked
var tid = $(this).attr('aria-trackid'), // get its track id
tiW = 'w' + tid + 'w',
tiW = eval(tiW); // set the waveform object
playPauseButton(this, tiW, tid);
});
});
}
});
// player functionality
function playPauseButton(button, wave, trackID){ // once the function has been called
pausePrevious(button); // pause the previous track (this doesn't work when more ajax results are loaded)
var button = $(button);
if(wave.isPlaying()){ // if the wave is playing; stop it
button.removeClass("playing");
wave.pause();
} else { // vice versa
button.addClass("playing");
wave.play();
}
var waveDuration = wave.getDuration();
var nextTrack = ++trackID;
var checkAudioFinished = setInterval(function(){ // check if the audio has finished playing every second
if(wave.getCurrentTime() >= waveDuration){ // if it has
button.removeClass("playing"); // remove it's buttons "playing" class
$('#w' + nextTrack + 'w-trigger').trigger('click'); // play the next song on the playlist by incrementing the id
clearInterval(checkAudioFinished);
}
}, 1000);
}
function pausePrevious(b){
$(".playing").not(b).each(function(){ // when this function is triggered
$(".playing").trigger('click'); // pause all of the other tracks (by simulating the click of their pause buttons
$(".playing").removeClass("playing"); // remove it's class too
});
}
I feel these problems are occurring due to the use of $(document).ready();. Forcing these functions to only be available to those tracks that were already loaded. However, I am not sure.
Here is the HTML that gets sent back from each request (in 10s):
<div class="f-wave-send f-waveform-container">
<div aria-trackid="1" class="track-w__trigger" id="w1w-trigger"></div> <!-- the "1" is generated by PHP. it is incremented for every div !-->
<div class="f-waveform-outer-container">
<div aria-trackid="1" class="track-w__waveform" id="w1-w"></div>
<script>
var w1w = WaveSurfer.create({ // wavesurfer script (this is the "wave" object that is being triggered inside the playPauseButton() function !-->
container: '#w1-w',
barWidth: 2,
});
w1w.load('./player/audio/sampleaudio.mp3');
</script>
</div>
</div>
If anyone could give me insight as to what might be going on (or any tips in improving my code for that matter), it would be greatly appreciated!
Try this,
You should not bind an click event each time load happens and it should be moved out of your loadTracks, instead you shuold apply event delegation.
// player functions
$(document).on('click', '.track-w__trigger', function(){ // when the play button is clicked
var tid = $(this).attr('aria-trackid'), // get its track id
tiW = 'w' + tid + 'w',
tiW = eval(tiW); // set the waveform object
playPauseButton(this, tiW, tid);
});
Change your code to this
$(document).ready(function(){ // on page load
var tp = 1; // set track page equal to one
loadTracks(tp); // then load all of the tracks
jQuery(function($) {
$('.f-outer-container').on('scroll', function() { // when the user scrolls to the bottom of the page load more tracks
if($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
tp++;
loadTracks(tp);
}
});
});
function loadTracks(track_page){
$.post('/spectrum-rr/core/_func/functions/loadTrack.php', {'page': tp}, function(data){ // get send and get data from loadTrack.php
$("#f-ap__aj").append(data); // append those tracks in the feed
});
}
// player functions
$(".track-w__trigger").on("click",function(){ // when the play button is clicked
var tid = $(this).attr('aria-trackid'); // get its track id
tiW = 'w' + tid + 'w';
tiW = eval(tiW); // set the waveform object
playPauseButton(this, tiW, tid);
});
});
Just move out $(".track-w__trigger").click outside $.post and change it to $(".track-w__trigger").on("click",function()

Photoswipe pswp class Not Clearing After Closing Image

I have a Photoswipe (http://photoswipe.com) image gallery on my site, and the css class is not resetting/clearing to remove the view after I close a gallery for the second time.
ex.
User opens item 1, AJAX populates the figure(s) into the picture div.
User clicks an image from item 1 and Photoswipe opens the image properly (setting the following class):
class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible"
User closes the image from item 1, class resets as normal:
class="pswp"
User closes item 1 and JS/JQuery clears all html in picture div. User opens item 2, AJAX populates the figure into the picture div. User clicks an image from item 2 and Photoswipe opens the image properly setting the same class as before.
class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible"
This is where the problem occurs. User closes the image from item 2 and the only thing that changes is:
aria-hidden="true"
but the class does not clear, it remains:
class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible"
when it should change to:
class="pswp"
This disables all interaction on the website since there is an invisible div/class on top of everything. The class needs to be changed back to pswp somehow.
AJAX/JS To Populate picture div (I added an id to the div):
if (i == 0) {
$('#listing_photos_container').append('<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject"><img src="' + json[i].image_url + '" height="400" width="600" itemprop="thumbnail" alt="listingPhoto" class="listing-photo"></figure>');
} else {
$('#listing_photos_container').append('<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject" class="listing-photo-holder"><img src="' + json[i].image_url + '" height="400" width="600" itemprop="thumbnail" alt="listingPhoto" class="listing-photo-holder"></figure>');
}
JS/JQuery to clear photo div:
$('#listing_photos_container').html('');
EDIT: The click listener function is running twice when a users clicks the photo to bring full screen. This is the code for the listener:
$.ajax({
type: "POST",
url: 'http://example.com/action?action=photos',
data: {id: id},
success: function (data) {
console.log('API Call - Photos');
json = JSON.parse(data);
$('#listing_photos_container').html('');
for (var i = 0; i < json.length; i++) {
// Styling code here
}
$('#list_header').html(
(function($) {
$('.picture').each( function() {
var $pic = $(this),
getItems = function() {
var items = [];
$pic.find('a').each(function() {
var $href = $(this).attr('href'),
$size = $(this).data('size').split('x'),
$width = $size[0],$height = $size[1];
var item = {
src : $href,
w : $width,
h : $height
}
items.push(item);
});
return items;
}
var items = getItems();
console.log('Items for PSWP' + items);
alert('Alert Point 1'); // This is called once, (as it should).
var $pswp = $('.pswp')[0];
$pic.on('click', 'figure', function(event) {
// This block is called twice..
alert('Click Funct');
event.preventDefault();
var $index = $(this).index();
var options = {
index: $index,
bgOpacity: 0.7,
showHideOpacity: true
}
// Initialize PhotoSwipe
alert('Setting new PhotoSwipe');
var lightBox = new PhotoSwipe($pswp, PhotoSwipeUI_Default, items, options);
lightBox.init();
}); // End $pic.on
});// End .picture each
})(jQuery)
); // End list_header.html
} // End AJAX Success
}); // End AJAX
You may have already fixed this, but in case someone else falls upon this.
This can happen if you trigger opening the gallery more than once without closing it. It may be that you have registered multiple click handlers to open the gallery or for some reason the event is being fired twice.
It happens because in the init function the current class name of the pswp element is retrieved and cached, then on destroy the class name is restored. When the second open occurs without destroy being called _initialClassName will be set to class="pswp pswp--supports-fs pswp--open pswp--animate_opacity pswp--notouch pswp--css_animation pswp--svg pswp--animated-in pswp--visible" as your are seeing
Line 776 of photoswipe.js where initialclass is set
_initalClassName = template.className;
Breakpoint this in your browser to see if it is called multiple times when opening
Line 942 onwards destroy function
destroy: function() {
_shout('destroy');
Breakpoint this in your browser to ensure it is being called for every time open is called
Final Solution
The problem is that when opening the popup and loading the images you are filling #listing_photos_container with your photos, then adding a click handler to open photoswipe. This click handler is added to the top element, so will remain when the popup is closed, then the next time it is opened a new click handler will be added.
To fix this you just need to unbind the click handler when closing the popup, you can do this with $(".picture").off('click'); somewhere inside your closeListing() function
It's quite simple, before every .click(...) you need to write .unbind('click').
Example:
$('a#open-photoswipe').unbind('click').click(function() {
// open photoswipe here
});
Was having similar problem - just define lightBox as global variable. And on destroy define it as null. And in beginning of function where You initialize lightBox just check if lighBox is already defined, then do return.

How to alert something when a div loaded with content

I have a a page that contains search toolkit. So when the search button is clicked, results will be fetched by a ajax from database and appended to a div.
It also shows number of records retrieved from database! I want to be able to do something immediately after the counter shows up a value.
I tried on click of the search button, but it only shows from the second click onward. Because when first clicked the search button, the data were not even fetched from database. Also, after data loaded, when click again it actually shows number of previously fetched records.
I thought, jquery's load() would suit better, but it doesn't too. Below are my attempts that failed. Can anyone suggest the best method please?
//This shows number of items fetched from database
len=data.length;
$(".len").append("<span class='light_blue' id='found'>"+len+"</span>
<span class='rm2' id='tname'> Tutors found</span>");
//This is how the results (fetched data) are appended into a div to be shown in the search page!
$(".the-inner-return").append("
All I want to do is to alert the count (basically I want to replace the text for id='tname' with something else when the count is 0 and 1 and more then 1).
Failed attempts:
$("#search").on("click",function()
{
alert($("#found").text());//alerts the count
});
$(".the-inner-return").on("load",function()
{
alert($("#found").text());//alerts the count
});
$(document).on("click", "#search",function(){
alert($("#found").text());//alerts the count
});
$(document).on( "load", ".the-inner-return", function() {
alert($("#found").text()); //alerts the count
});
You can trigger an alert each time the innerHTML for .len gets changed, for instance like this you get an alert whenever len>0:
$('.len').bind("DOMSubtreeModified", function () {
if (len > 0) {
alert('changed');
}
});
len = 5;
$('.len').bind("DOMSubtreeModified", function() {
if (len > 0) {
alert('>0');
}
});
$(".len").append("<span class='light_blue' id='found'>" + len + "</span><span class='rm2' id='tname'> Tutors found</span>");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="len"></div>

JScrollPane Plugin - Reinitialize on Collapse

I'm trying to get JScrollPane to reinitialize on expand/collapse of my accordion found here. You can demo the accordion by clicking on one of the parents (Stone Tiles, Stone Sinks, Stone Wall Clading, etc).
Right now I set it as a click event using the following JQuery...
var pane = $('.menuwrap')
pane.jScrollPane();
var api = pane.data('jsp');
var i = 1;
$("ul#widget-collapscat-5-top > li.collapsing").click(function() {
$(this).delay(3000);
api.reinitialise();
});
It seems to work when you click the parent the second time, but not the first. I have no idea why but I went into trying to edit the JS for the accordion so that I can add this function when the collapse is complete (as opposed to trying to do this click workaround). The collapse JS can be viewed here.
I tried to add the JS for the reinitialize function here, but I think I'm not doing something properly.
May you point me in the right direction?
Thanks!
The api.reinitialise() is working properly. What is happening is that it updates the size when you click, and at this moment the element is not expanded yet. You may notice that if you expand, colapse and expand again the same section, nothing happens. But if you expand one and then click another one, the ScrollPane will adjust to the size of the first expanded element.
You can solve this with events: place $(this).trigger('colapseComplete') when the colapse ends. Then you can use:
//Listening to the colapseComplete event we triggered above
$("#widget-collapscat-5-top > li.collapsing").on('colapseComplete', function() {
api.reinitialise();
});
Maybe you can alter the addExpandCollapse function to call the reinitialise function at the end of each of its click actions this way :
function addExpandCollapse(id, expandSym, collapseSym, accordion) {
jQuery('#' + id + ' .expand').live('click', function() {
if (accordion==1) {
var theDiv = jQuery(this).parent().parent().find('span.collapse').parent().find('div');
jQuery(theDiv).hide('normal');
jQuery(this).parent().parent().find('span.collapse').removeClass('collapse').addClass('expand');
createCookie(theDiv.attr('id'), 0, 7);
}
jQuery('#' + id + ' .expand .sym').html(expandSym);
expandCat(this, expandSym, collapseSym);
api.reinitialise(); // HERE
return false;
});
jQuery('#' + id + ' .collapse').live('click', function() {
collapseCat(this, expandSym, collapseSym);
api.reinitialise(); // and HERE
return false;
});
}
and to be on a safer side, make sure you have the var api = pane.data('jsp'); line before the above piece of code anywhere in the file.

Categories

Resources