First, my thanks to everyone who has contributed to views_slideshow, it is awesome.

This may be a feature request, but here goes as a support question.

Is there some way to have the views slideshow auto pause when it is off the browser screen and resume when the browser screen is scrolled back to show the slideshow?

Thanks,

Izzy

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

redndahead’s picture

You would have to add javascript Here is a small function that checks to see if it is visible. You'll need to set a timeout to check for visibility so it can now if and when to pause it. I haven't tried this so there may be some bugs.

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

//Wrap this in a timeout.
var isPaused = false;
if (isScrolledIntoView('#my_id') && isPaused) {
  $('#my_slideshow_id').cycle('resume');
  isPaused = false;
}
else if (!isScrolledIntoView('#my_id') && !isPaused) {
  $('#my_slideshow_id').cycle('pause');
  isPaused = true;
}
izmeez’s picture

Thanks for the fast response.

Sorry I'm new to this. Can you help me with the steps:

Do I just place this in a separate file or add it to an existing file?
Where do I need to put the file?
And how do I set the timeout?

Izzy

redndahead’s picture

This would be a separate file. You can add it through your theme .info file by doing scripts[] = yourscript.js

Here is a rewritten one with the timeout. It's set to check every 100ms.

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

function checkStatus() {
  var isPaused = false;
  if (isScrolledIntoView('#my_id') && isPaused) {
    $('#my_slideshow_id').cycle('resume');
    isPaused = false;
  }
  else if (!isScrolledIntoView('#my_id') && !isPaused) {
    $('#my_slideshow_id').cycle('pause');
    isPaused = true;
  }

  // Timeout is set here.  Checks every 100ms.
  setTimeout("checkStatus()",100);
}

checkStatus();
izmeez’s picture

Again, thanks for all the help.

I have copied the code and added the following line to the theme info file in my zen subtheme:

scripts[] = scrolled_into_view.js

It does not appear to be working and I am getting 1 error with firebug.

I turned off js aggregation but still not really sure how to debug this.

I'm willing to try whatever you can suggest.

Thanks,

Izzy

redndahead’s picture

You need to make sure the #my_slideshow_id is replaced with the actual id's from your slideshow

So #my_id would change to something like

.view-slideshow

and #my_slideshow_id would change to something like

.views_slideshow_singleframe_teaser_section

If you use these values then it's going to effect every slideshow you have on your site so you'll probably have to be more specific in your css if you have multiple slideshows. Also don't forget to clear your cache.

izmeez’s picture

Just to test this out I used '.view-slideshow' and '.views_slideshow_singleframe_teaser_section' in both places, but still to no avail.

[edit] I also tried '.views-slideshow' without success, I did leave the quotes [/edit]

Yes, I cleared the cache.

I also cleared Firebug errors and they are not returning so that may be unrelated.

But, unfortunately the auto pause is not working.

I am using Firefox 3.6.2 and might have to test on other browsers.

Do I have to add something else to the css besides the one line scripts[] =

Thanks very much for your help and persistence.

Izzy

redndahead’s picture

I think I've gone as far as I can go without looking at a site. Is there a site I can look at so I can test this?

redndahead’s picture

Ok here is some adjusted code. Pay specific attention to the checkStatus call on the very last line. There is an id there that corresponds to the id of the div that wraps all the slides. Replace it with your id. I have confirmed this to work on my test instance. It will pause it unless the entire slideshow is showing.

function isVisible(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

function checkStatus(slideId) {
  if (typeof Drupal.settings.slideshowIsPaused == 'undefined') {
    Drupal.settings.slideshowIsPaused = false;
  }
 
  if (isVisible(slideId) && Drupal.settings.isPaused) {
    $(slideId).cycle('resume');
    Drupal.settings.isPaused = false;
  }
  else if (!isVisible(slideId) && !Drupal.settings.isPaused) {
    $(slideId).cycle('pause');
    Drupal.settings.isPaused = true;
  }

  // Timeout is set here.  Checks every 100ms.
  setTimeout("checkStatus('" + slideId + "')",100);
}

checkStatus('#views_slideshow_singleframe_teaser_section_slideshow-page_1');
izmeez’s picture

@redndahead, You have been incredible. Sorry, I had to head off to a Drupal users meeting.

I just tried the new code and I'm still having problems with the auto pause not working.

Yes, I do have a site you can view if you don't mind. I'll send you the link through your contact form.

Thanks.

redndahead’s picture

I have some bad code up there.

Try this

function isVisible(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

function checkStatus(slideId) {
  if (typeof Drupal.settings.slideshowIsPaused == 'undefined') {
    Drupal.settings.slideshowIsPaused = false;
  }

  if (isVisible(slideId) && Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('resume');
    Drupal.settings.slideshowIsPaused = false;
  }
  else if (!isVisible(slideId) && !Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('pause');
    Drupal.settings.slideshowIsPaused = true;
  }

  // Timeout is set here.  Checks every 100ms.
  setTimeout("checkStatus('" + slideId + "')",100);
}

checkStatus('#views_slideshow_singleframe_teaser_section_frontpage-block_1');
izmeez’s picture

Thanks, but it's still not working.

I've also been taking a look at firebug and I'm getting a jquery error when loading or refreshing the page.

I'm not sure what is causing this and out of my depth to offer more than just the willingness to test things and learn.

I really appreciate all your effort.

redndahead’s picture

One more adjustment

function isVisible(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

function checkStatus(slideId) {
  if (typeof Drupal.settings.slideshowIsPaused == 'undefined') {
    Drupal.settings.slideshowIsPaused = false;
  }

  if (isVisible(slideId) && Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('resume');
    Drupal.settings.slideshowIsPaused = false;
  }
  else if (!isVisible(slideId) && !Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('pause');
    Drupal.settings.slideshowIsPaused = true;
  }

  // Timeout is set here.  Checks every 100ms.
  setTimeout("checkStatus('" + slideId + "')",100);
}

$(document).ready(function() {
  checkStatus('#views_slideshow_singleframe_teaser_section_frontpage-block_1');
});
redndahead’s picture

Status: Active » Postponed (maintainer needs more info)
izmeez’s picture

This is fantastic. It works like a charm. Thank you very much. Hope I get to thank you in person one day.

When you get a chance ...

As is the slide show auto pauses whenever the slide is not fully visible.

What would I need to change to keep the slide show active even if x% of the bottom is not visible?

This would keep the slide show going if some slides are larger such that the bottom portion of the slide might be out of visible range.

Thanks

izmeez’s picture

There may still be another tweak needed.

It works great on the page that has the views slideshow but on all other pages I am getting a javascript error.

$(elem).offset() is undefined
var elemTop = $(elem).offset().top; 

Not sure why.

redndahead’s picture

This fixes the error.

function isVisible(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
      && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
}

function checkStatus(slideId) {
  if (typeof Drupal.settings.slideshowIsPaused == 'undefined') {
    Drupal.settings.slideshowIsPaused = false;
  }

  if (isVisible(slideId) && Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('resume');
    Drupal.settings.slideshowIsPaused = false;
  }
  else if (!isVisible(slideId) && !Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('pause');
    Drupal.settings.slideshowIsPaused = true;
  }

  // Timeout is set here.  Checks every 100ms.
  setTimeout("checkStatus('" + slideId + "')",100);
}

$(document).ready(function() {
  var slideshow = '#views_slideshow_singleframe_teaser_section_frontpage-block_1';
  if ($(slideshow).length) {
    checkStatus(slideshow);
  }
});

[Edit] I fixed a bug [/Edit]
This may handle the percentage. Not tested so may die completely or not work.

function isVisiblePercent(elem, percent)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemHeight = $(elem).height();
    var elemBottom = elemTop + elemHeight;

    var missing = 0;
    if (elemTop < docViewTop) {
      missing += docViewTop - elemTop;
    }

    if (elemBottom > docViewBottom) {
      missing += elemBottom - docViewBottom;
    }

    return (((missing/elemHeight)*100) < (100 - percent));
}

function checkStatus(slideId, percent) {
  if (typeof Drupal.settings.slideshowIsPaused == 'undefined') {
    Drupal.settings.slideshowIsPaused = false;
  }

  if (isVisiblePercent(slideId, percent) && Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('resume');
    Drupal.settings.slideshowIsPaused = false;
  }
  else if (!isVisiblePercent(slideId, percent) && !Drupal.settings.slideshowIsPaused) {
    $(slideId).cycle('pause');
    Drupal.settings.slideshowIsPaused = true;
  }

  // Timeout is set here.  Checks every 100ms.
  setTimeout("checkStatus('" + slideId + "', " + percent + ")",100);
}

$(document).ready(function() {
  var slideshow = '#views_slideshow_singleframe_teaser_section_frontpage-block_1';
  var percent = 80; // The percentage of the slide that has to be visible.
  if ($(slideshow).length) {
    checkStatus(slideshow, percent);
  }
});
redndahead’s picture

Category: feature » support
Status: Needs review » Postponed (maintainer needs more info)

Now to wrap it all up into one nice package. Here is a version that will allow you to enter in the percentage that needs to be shown before it is paused or the amount of the slide height in px that needs to be shown before it is paused. Also if you don't specify anything then it will require the entire slideshow to be shown. Alot more documentation added also to hopefully help you understand the code. This has been tested on my local machine.


/**
 * Checks to see if the slide is visible enough.
 * elem = element to check.
 * amountVisible = amount that should be visible. Either in percent or px. If
 *                it's not defined then all of the slide must be visible.
 *
 * Returns true or false
 */
function isVisible(elem, amountVisible) {
  // Get the top and bottom of the window;
  var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  // Get the top, bottom, and height of the slide;
  var elemTop = $(elem).offset().top;
  var elemHeight = $(elem).height();
  var elemBottom = elemTop + elemHeight;
  
  // If there is no amountVisible defined then check to see if the whole slide
  // is visible.
  if (typeof(amountVisible) == 'undefined' || amountVisible == '') {
    return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
    && (elemBottom <= docViewBottom) &&  (elemTop >= docViewTop) );
  }
  else {
    var missing = 0;
    
    // Find out how much of the slide is missing from the top.
    if (elemTop < docViewTop) {
      missing += docViewTop - elemTop;
    }

    // Find out how much of the slide is missing from the bottom.
    if (elemBottom > docViewBottom) {
      missing += elemBottom - docViewBottom;
    }
    
    // If user specified a percentage then find out if the current shown percent
    // is larger than the allowed percent.
    // Otherwise check to see if the amount of px shown is larger than the
    // allotted amount.
    if (isNaN(amountVisible)) {
      return (((missing/elemHeight)*100) < (100 - parseInt(amountVisible)));
    }
    else {
      return (missing < (elemHeight-amountVisible));
    }
  }
}

/**
 * Pauses the slideshow if not enough of it is showing.
 * slideId = The ID of the slide
 * amountVisible = The amount in pixels or percentage that has to be visible.
 */
function pauseIfHidden(slideId, amountVisible) {
  // Make sure the id exists on the page.
  if ($(slideId).length) {
    console.info('hello');
    // Check everytime the user scrolls the page.
    var slideshowIsPaused = false;
    $(window).scroll(function() {
      // If the slideshow is visible and it is paused then resume.
      // otherwise if the slideshow is not visible and it is not paused then
      // pause it.
      if (isVisible(slideId, amountVisible) && slideshowIsPaused) {
        $(slideId).cycle('resume');
        slideshowIsPaused = false;
      }
      else if (!isVisible(slideId, amountVisible) && !slideshowIsPaused) {
        $(slideId).cycle('pause');
        slideshowIsPaused = true;
      }
    });
  }
}

// This calls our pause function.
$(document).ready(function() {
  /**
   * pauseIfHidden(slideshow [, amountVisible]);
   * slideshow = the ID of the div wrapping the slideshow.
   * amountVisible = either the percentage or the amount in px that needs to be
   *                 showing before it is paused.
   * If you don't specify the amountVisible then it will require the whole slide
   * to be visible.
   *
   * Usage examples:
   * // Requre the whole slideshow to be shown.
   * pauseIfHidden('#views_slideshow_singleframe_teaser_section_frontpage-block_1');
   *
   * // Require 50% of the slideshow to be shown.
   * pauseIfHidden('#views_slideshow_singleframe_teaser_section_frontpage-block_1', '50%');
   *
   * // Require 250px in height of the slideshow to be shown.
   * pauseIfHidden('#views_slideshow_singleframe_teaser_section_frontpage-block_1', 250);
   */
  pauseIfHidden('#views_slideshow_singleframe_teaser_section_frontpage-block_1');
});
izmeez’s picture

Wow!

I won't have time to test this before dawn tomorrow but will let you know as soon as I do.

Thanks,

PS. I think this really counts as a feature, but will leave the issue fields as is for now.

redndahead’s picture

Category: support » feature
Status: Postponed (maintainer needs more info) » Needs review
FileSize
11.37 KB

And a patch would look something like this. Adds a new option Pause When the Slideshow is Not Visible

intyms’s picture

Category: support » feature
Status: Postponed (maintainer needs more info) » Needs review

Thank you for new features !

I tested the patch in thumbnail mode:

My actions:
I set the value to 50%;
I scroll down. And i see that the slideshow stops.

I scroll left but i see that the slideshow does not stop.
Can this feature be implemented for use with horizontal scroll?

redndahead’s picture

I'll look into it. Will complicate things quite a bit more. It will become how much of the total slide is visible. And I'll have to figure out how I can calculate the visible area of the slide.

redndahead’s picture

Just so I can come back and look at it.

area_showing = (total_width - left_missing - right_missing) * (total_height - top_missing - bottom_missing)

Maybe this should add another select option.

Pause if any portion of the slide is not visible
Pause based on amount horizontal visible
Pause based on amount vertical visible
Pause based on amount of the total area that is visible

izmeez’s picture

I don't think you need amount totally visible, just horizontal and vertical. It's about position not area.

redndahead’s picture

Let's say you set it to 50% horizontal
Then you move it so 51% horizontal is showing.
Then you move the slide so only 1px of it is showing vertical.
It will still rotate because 51% of the horizontal is showing.

izmeez’s picture

I thought it would be an OR not an AND, so if either the horizontal or the vertical were showing less than 50% it would pause.

redndahead’s picture

Here is one that takes care of all options. Please test.

izmeez’s picture

Patch in #26 applies without any problems and works great for vertical tests.

Both the "Set amount of vertical" and "set total area of slide" do the job.

Haven't setup a horizontal test case so can't comment there. Maybe someone else can.

Seeing how well it works, I'd be inclined to move the "Set total area of slide" to the second option under "Entire slide" and who knows, it might be the best choice all round.

It might be a bit confusing to understand is the presumption that this is the total area from the center of the slide, or the top left corner? Maybe, the option can be "Set total area from center of slide".

And I also had a momentary mind curl when I wondered, since this is 2D is 50% really 1/4, you know 1/2 the width and 1/2 the height :-)

Oh yes, the jquery errors on other pages are gone.

Thanks very much. You've been awesome.

intyms’s picture

#26 redndahead
Thanks for the patch.

  • I think it will be better to place "Amount of Slide Needed to be Shown:" inside of the "Pause When the Slideshow is Not Visible" container.
  • "Pause When the Slideshow is Not Visible" is hard to find. Changing font-weight to bold will solve this.
  • The value inside of the "Amount of Slide Needed to be Shown" is not saving.
    How to reproduce:
    Check "Pause When the Slideshow is Not Visible"
    Choose "Set total area of the slide"
    Enter 50% for the Amount of Slide Needed to be Shown
    Press "Update"
    Click the gear to edit the Slideshow style once again.

I applied the patch to VS 6.x-2.2. I am using Views 6.x-2.11.

izmeez’s picture

@intyms

I'm not sure what the difference is but "Amount of slide needed to show" is saving for me.
I'm using VS 6.x-2.2 with the patch and Views 6.x-2.x-dev dated 2010-Jun-17

intyms’s picture

Firstly i applyed the patch no.1 (#19) and configured my slideshow to stop when the height is less than 50%.
Then i deleted the VS directory and downloaded a new one.
Then i applied the patch no.2 (#26).

Maybe "Amount of slide needed to show" is not saving because of the conflict between these 2 patches?

redndahead’s picture

Fixed spelling error that fixes #1 and #3

#2 unfortunately this is a side effect of form api and checkboxes. Themes don't mark this as bold. I don't plan on changing the css because I feel it's the themes job to take care of that.

intyms’s picture

@#31 redndahead
Hello thanks for quick patch.
Tested it using thumbnailhover mode ("Set total area of the slide" and "set amount of horizontal")

The value inside of the "Amount of Slide Needed to be Shown" is saved now. Thanks.

  1. "Amount of Slide Needed to be Shown:" is showing even if "Pause When the Slideshow is Not Visible" isn't checked.
  2. The slideshow stops only if we change the visibile part of the slideshow using scroll (scrollbars). However, if we resize the browser window, the slideshow will not stop.

Everything else is working well.

redndahead’s picture

Status: Needs review » Needs work

I'll look into #1

#2 was kind of a trade off. I figured not many people would run into the resize issue, otherwise I think I would have to keep polling the window and I didn't want to waste those resources.

redndahead’s picture

I really appreciate you guys really testing this. It helps out tremendously.

Fixed #1 and #2

izmeez’s picture

@redndahead #34
Patch 4 including the new fixes works for me. But, in singleframe mode resizing the browser horizontal width causes the block to overflow into the right sidebar. May be because of page caching although other blocks seem to cope. Flushing all caches after resizing corrects it.

Thanks.

redndahead’s picture

Status: Needs work » Needs review

Yeah nothing in that patch deals with layout. So it must have been something else. Thank you for testing.

@intyms if you feel this patch is good then please mark RTBC

intyms’s picture

@#34 redndahead
Thanks for the patch.

  1. Since the patch also stops the slideshow when the browser window is resized, we need to change this text to match the new feature of the patch.
    "When the slideshow is scrolled out of view this will pause the slideshow.
    Resizing the browser window to hide a part of the slideshow, will force the slideshow to stop playing"
    Sorry for my english ;)
  2. I choose "set amount of horizontal". I write 50% in the textfield.
    Update and save the view.
    Then i resize the browser window to +/- 40% of the slideshow width;
    The slideshow still is playing.
    The slideshow will stop to play when the window will resize to +/- 30% of the slideshow's width.
  3. Also other help text has to be modified in order to provide more details to the user. I suggest to modify it when this feature will work 100%
intyms’s picture

Status: Needs review » Needs work
izmeez’s picture

This might not be of high importance to some, but if a client user base consists of many people whose desktops are still configured for IE6 it becomes essential. I also don't know at this time if other versions of IE are affected. More tests are needed.

The problem occurs when a user visits a page containing a VSS with the pause when not visible. (I have not tested without the pause setting, yet.)

If they stay on that page long enough for the slideshow to change IE6 will freeze and become "not responding".

If they quickly scroll so the slideshow is not visible and the slideshow pauses or they navigate away to a page that does not include a slideshow IE continues to remain responsive.

I tried changing the VSS IE options to no avail.

Is this problem related to this patch or is it a separate issue? I do not know.

Thanks.

izmeez’s picture

I am wondering if the problems I am experiencing with IE6 are related to the fade effect as described in another issue http://drupal.org/node/249081

I am using fade-zoom.

I don't know if I should reopen that issue or start a new issue to not contaminate the current feature request for auto pause which this issue and the patches here are about.

Thanks.

izmeez’s picture

ok, I can confirm the pause when not visible works well with IE6 using singleframe mode.

The problem I encountered is that many of the singleframe effects do not work with IE6. But, there are a few that do. So rather than hijacking this issue any further I can post a new issue as a support ticket and answer the question myself with details for anyone else interested in that problem.

Thanks very much for the pause when not visible feature. Even though it may need some work it is already a ++ for me.

redndahead’s picture

Status: Needs work » Needs review
FileSize
18.32 KB

@intyms
This patch fixes #1 and #2. Can you give suggestions on where I can improve the help text?

intyms’s picture

Status: Needs review » Needs work

@42
Thanks for patch. it's working great!

We can change this:
The amount of the slide that needs to be shown to have it rotate. You can set a percentage such as 50% or the height in px such as 250.

New version of the text:
The amount of the slide that needs to be shown to have it rotate. You can set the value in percentage (ex: 50%) or in pixels (ex: 250).
The slidehsow will not rotate until it's height (or width, total area) is less than the value you have entered in this field.

redndahead’s picture

Status: Needs work » Fixed
FileSize
18.67 KB

This patch was committed thanks everyone!!! This was an awesome issue to work on.

intyms’s picture

Great thanks to you too.
Congratulations with a new nice feature!

izmeez’s picture

Yes, my thanks too.

The feature is great and the process was fantastic.

I'll pick it up in this morning's dev release.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.