Pagination for shop page and pages width


#41

Sounds great!


#42

So, I didn't even needed to resolve the width bug. Looks like this bug is on masonry because once I enforced some widths to make it into 3 columns it just went away (along with the side shifting).

I believe all the rest is done and all bugs gone! But I'll only be able to test on iPad later on, maybe tomorrow.

Let me know if you need me to record a short video to show you what have been done.

There are a few things needed to recreate it from scratch, if needed (right now you could just use the new-shop page straight on):

1) A page with a grid summary block inside and displaying thumbnail and price only (haven't even tested with other options). Column width here won't matter. Paging will be based on the number of items (currently set to 12).

2) That page also need to have an animated GIF with the loading image, and a clickthrough URL link to javascript:endlessScrollingLoading();

3) Still on the same page, copy and paste the script to that page's advanced settings, under page header code injection (for future reference, keep in mind the version pasted below might be outdated):

<script src="http://cdnjs.cloudflare.com/ajax/libs/masonry/3.3.0/masonry.pkgd.min.js"></script>
<script src="https://cdn.rawgit.com/desandro/imagesloaded/master/imagesloaded.pkgd.min.js"></script>
<script name="endless scrolling" author="cregox.com">
  // mostly based on script from foley at http://answers.squarespace.com/questions/17153/how-can-i-create-an-infinite-scroll-blog-on-the-developer-platform

  Y.use('node', function()
  {
    Y.on('domready', function()
    {
      Y.one('main#main').addClass('endless-scrolling');

      // prevent script from running in squarespace editor
      if (window.top.document !== window.document) return;

      // config
      var loadingMargin = 500; //px
      var parent = 'main#main .wrapper';
      var list = '.summary-item-list';
      var post = '.summary-item';

      // private
      var jsonCachedRequest = null;
      var YparentToAppend;
      var YnewItemsToClone;
      var pageSize = 0;
      var pageIndex = 1;
      var totalItemsCount = 0;// Static.SQUARESPACE_CONTEXT.collection.itemCount;
      var execute;
      var urlQuery = window.location.pathname;
      var stuffBottom;
      var currentItemsCount;
      var YloadingIcon;
      var msnry;
      var YnewItems;

      YparentToAppend = Y.one(parent).one('div');
      cacheAjaxRequest();

      setMouseHover(YparentToAppend);

      YloadingIcon = Y.one('a[href^="javascript:endlessScrollingLoading"]');

      // while there's no proper function to go back to a specific item, this should let the browser do the trick
      YparentToAppend.all('.summary-item a').set('target', '_blank');
      
      // basically all styles set in this whole script need to be set here
      // to overwrite styles already set on the element before this
      YparentToAppend.all('.summary-item').setStyle('width', 'initial');
      
      YloadingIcon.one('img').setStyles({
        'top': 'initial',
        'bottom': 0,
        'left': 'initial',
        'right': 'initial',
        'width': 'initial',
        'height': 'initial',
        'position': 'initial'
      }).addClass('endless-loading').get('parentNode').setStyle('text-align', 'center');
      YloadingIcon.one('div.image-block-wrapper').setStyle('padding-bottom', 0);
      Y.one(parent).append(YloadingIcon);
      
      YnewItemsToClone = YparentToAppend.one('.summary-item-list').cloneNode(true);
      YnewItemsToClone.hide();
      pageSize = YnewItemsToClone.all('.summary-item').size();

      Y.one(parent).setStyles({
        'background-color': '#e8edf3',
        'padding': '2em'
      });
      Y.one('footer#footer').hide().setStyles({
        'position': 'absolute',
        'bottom': 0,
        'left': '10px',
        'right': '10px'
      });

      loadMasonry(); loadMasonry(); // loading twice just works

      Y.on('scroll', function()
      {
        if (currentItemsCount >= totalItemsCount && execute === true)
        {
          YloadingIcon.remove(true);
          Y.one('footer#footer').show();
          execute = false;
        }
        else
        {
          var spaceHeight = document.documentElement.clientHeight + window.scrollY;

          // measures distance from page top to content bottom
          // should be less than scrollY position
          if (spaceHeight + loadingMargin >= stuffBottom && execute === true)
          {
            // prevents scroll listener from firing too often
            execute = false;

            createPage();

            loadMasonry(); loadMasonry(); // loading twice just works
          } // if bottom
        } // else execute
      }); // Y on scroll

      function loadMasonry ()
      {
        var container = document.querySelector(list);
        msnry = new Masonry( container,
        {
          'transitionDuration': 0,
          'gutter': 15,
          'itemSelector': '.summary-item',
          'isInitLayour': false
        });
        
        msnry.on( 'layoutComplete', function( laidOutItems )
        {
          if (YnewItems) YnewItems.show();
          resetScrollingVars();
          return true; // listen to event only once
        });
        imagesLoaded( container, function()
        {
          msnry.layout();
        });
      }

      function resetScrollingVars ()
      {
        Y.one('body').simulate('resize'); // adjust items in the columns
        
        stuffBottom = Y.one(parent).get('clientHeight') + Y.one(parent).getY();
        currentItemsCount = Y.all(post).size();
        execute = true;
      }

      function createPage ()
      {
        if (jsonCachedRequest === null) return;

        pageIndex++;

        var json = jsonCachedRequest;
        var YnewItemsToDelete = YnewItemsToClone.cloneNode(true);

        YnewItemsToDelete.all('img').setStyle('opacity', 1);
        YnewItems = YnewItemsToDelete.all('.summary-item').hide();

        for (var i = pageSize - 1; i >= 0; i--)
        {
          var j = (pageIndex - 1) * pageSize + i;
          if (j >= totalItemsCount)
          {
            YnewItems.item(i).hide().empty().remove(true);
            YnewItems.pop(i);
          }
          else
          {
            YnewItems.item(i).one('a').set('href', json.items[j].fullUrl);
            YnewItems.item(i).one('img').set('src', json.items[j].assetUrl);
            YnewItems.item(i).one('.product-price span').setContent(
              (json.items[j].variants[0].price / 100).toFixed(2)
            );
          }
        }

        setMouseHover(YnewItemsToDelete);
        YparentToAppend.one('.summary-item-list').append(YnewItems);
        YnewItemsToDelete.remove(true);
      } // function createPage

      function cacheAjaxRequest ()
      {
        if (jsonCachedRequest === null)
        {
          // ajax request
          Y.io('/shop?format=json', {
            on: {
              success: function (x, o) {
                try {
                  json = Y.JSON.parse(o.responseText);
                } catch (e) {
                  console.log("JSON Parse failed!");
                  return;
                }

                jsonCachedRequest = json;
                totalItemsCount = json.items.length;
                resetScrollingVars();
              }
            }
          });
        }
      } // function cachedAjaxRequest

      function setMouseHover (Ynode)
      {
        Ynode.all('.summary-item img').on('mouseenter', function(e)
        {
          e.currentTarget.transition(
            {
              duration:0.5,
              opacity:0.5
            });
        });
        Ynode.all('.summary-item img').on('mouseleave', function(e)
        {
          e.currentTarget.transition(
            {
              duration:0.5,
              opacity:1
            });
        });
      } // function setMouseHover

    }); // Y on DOMready
  }); // Y use node
</script>

4) Copy and paste the LESS / CSS into Custom CSS (again, for future reference, keep in mind the version pasted below might be outdated):

// endless scrolling by cregox.com
body main#main {
  width: ~'calc(100% - 240px)';
}

main#main.endless-scrolling {
  .summary-item {
    margin: 0 !important;
    width: ~'calc(33.33% - 10px)' !important; // 3 columns
    @media screen {
      @media (max-width: 880px) { // switch
        width: ~'calc(50% - 8px)' !important; // 2 columns
      }
      @media (max-width: 550px) { //switch
        width: 100% !important; // 1 column
      }
    }
  }
  .summary-thumbnail.img-wrapper {
    padding-bottom: 0 !important;
    img {
      background-color: rgba(17,17,17,.05);
      position: initial !important;
      width: 100% !important;
      height: auto !important;
    }
  }
  .summary-price .product-price {
    position: absolute;
    bottom: 1em;
    right: 0;
    padding: 1em;
    span {
      font-size: 1em;
    }
  }
  @media screen and (max-width: 1024px) {
    width: 100%;
    div.wrapper>div {
      padding-top: 2em;
      height: 100%;
    }
  }
}

5) Tweak the CSS at your will, and have fun! yum

You may have noticed I've replaced the previous width: 80% css by this more complete calc solution, which is also important to help fixing a (now old) issue with the new shop width.

On a side note, I would keep and use the current shop as a print page, which will load all items at once. That can be useful eventually.


#43

The new-shop is looking really good. I'm sure I will need a video, I don't understand most of what you are telling me above.

I also don't understand how to implement the 'new-shop' into being the SHOP. Will the current shop need to remain somewhere? I noticed when you click on a product in the new-shop it seems to take you to the current shop. That is not how it will work once the new-shop is the main shop...correct?

I would like the functionality to be the same as the current shop, when you click on the product thumbnail you go to the product page within the site, not jump to another window.

I am not worried about anyone needing to print the shop.


#44

It is looking really good, isn't it? I liked it too. smile

I'll make the video tomorrow, no problem.

The "print function" wouldn't be just for printing... For one, it could be a good use for someone with a desktop and fast connection who are used with the shop the way it is. It's also a good use along with pocket, for another instance. I personally would prefer using the "pageless function", how it could also be called. But that's not such a big deal, and it would be easy to implement / remove in a matter of couple minutes.

I removed the "opening in new window", it's just a matter of commenting out this line:

  // while there's no proper function to go back to a specific item, this should let the browser do the trick
  YparentToAppend.all('.summary-item a').set('target', '_blank');

But that was there on purpose because I won't be able to implement the coming back to the same page. I'll show you on the video. Although, now I realize, looks like it's a functionality you might not even have been aware that existed before...

I must admit I haven't noticed there was a < SHOP button there leading to /shop, even while we're at the /new-shop. That's fairly simple to fix, but then when we go to /shop the reverse will happen: it'll lead to /new-shop.

Anyway, we could schedule a skype meeting for you to feel safer while I release it all as the official shop, we fix anything on the spot if something comes up, and we finish it up! How does this sound?


#45

yes, it looks good. it sounds like you can take care of the things i asked about. please send the video and i will watch to see if i understand. after that perhaps we can schedule a skype meeting. thanks


#46

when you click on a product page from the shop, then click back to the shop will you always default to the top of the shop page? i like it when you click back and land where you were before. how will it work in the new-shop?


#47

What you call "going back always default to the top" is what I've been trying to tell you. smile

This is way, way more complicated than it may look like. It's also something some browsers do and others don't (coincidentally, I've noticed at least Safari on iPad is actually already working out of the box). While I do want to implement it into the general solution I certainly won't be able to do it so soon. I can only ask you to wait for that future and/or take the new tab temporary solution.

As for the video, I'm running into some technical issues with making it today. I may not be able to do it before Monday.


#48

monday is fine for the video. i am going to re-read your messages and see if i can more clearly understand : )


#49

Video done:

The last piece of code needed to get on the shop page and fix the product item < SHOP "back" button is simplified below (to allow making the print link):

<script name="endless scrolling" author="cregox.com">
  Y.use('node', function()
  {
    Y.on('domready', function()
    {
      Y.all('a[href$="/shop/"]').set('href', '/new-shop/');
    });
  });
</script>

Keep in mind the scripts have a few lines that rely on both /shop and /new-shop page names, or URL Slug as it's called under page settings. If you rename any of the two pages, please remember to rename it there in the code too. Fortunately that shouldn't happen that often!


#50

I noticed on my iphone and ipad that i can look at a product page then go back to where i was in the new-shop with the back button. It works perfectly as long as i don't hit the 'shop' link at the top of the text on the product page. when i try it on my laptop there seems to either be a loading delay or page does not finish loading. i also noticed sometimes when i hit the back button i land at the top of the shop page. is there a way to fix this? i do not want the product page to open in a separate tab. from your video is sounded like it would be very difficult or time intensive to fix. why is it working fine on my iphone and ipad, but not on my laptop? thanks


#51

Well, the < SHOP link at the top would have this exact same issue on the old shop. And most dynamic webpages are and always were like that. Stateless. Navigating back and forward will break each history page state, especially by using the browser history navigation.

That's why some browsers try to solve that issue.

iOS Safari's have an awesome persistent caching that the desktop or any Chrome doesn't. Some developers even think that's a problem, I consider it quite an awesome feature. Opera is another browser which used to have this feature and it was blazing fast but now it's the same. Firefox, for another instance, have it all different. It will cache the DOM, but not the images so it looks like it's reloading everything while it's just loading the images and the page rendering. Tor have the same feature as firefox but it loads so fast that it looks like iOS Safari.

Back to the < SHOP link issue, you may notice it's not the same function as pressing back on the browser. If you do press on the link, you'll see you can use the history back to go back to the product and then again to go back even further to the previous page, which coincidentally is the same link. Coincidentally.

In any case, we'll leave it not open in a separate tab (I also hate that in fact) and as I meant/told you before, when I get the time I'll continue improving the endless scrolling as my own investment. When I do, I update it for you.

And then even the shop link will work as a much better back button there! You see, if you open a new TAB and paste straight on an item address on the URL (such as this), you can't go back to the shop without that link. wink


#52

I appreciate your effort to create a work around. At this point I am ready to have our shop function differently that most shops out there. I am considering switching to a template that paginates, like Galapagos. Since I don't think the template allows me to choose how many products to show on each page...is that something you could fix without altering any other function/look of the template?

I really liked the idea of dynamic loading, but losing the history of the main shop page and/or opening a separate tab are not options I want. I really want the shop to function like it does currently.


#53

I actually just had an idea, but even this I initially thought would be simple, just was not.

You can see the idea implemented there right now. It's basically making a huge height so the browser can scroll down. The problem is the loading was already not working expecting for this, so it needed some tweaks to consider it. And when I've done then, I found some very weird bugs... Sometimes coding can become a real pain!

I've seen many endless scrolls implemented, but none as interesting as on google images, I just noticed (which hinted me the idea). Most of other infinite paging even on google can't go back as well. Ideally an endless scroll would be a mix of that with this of discourse here.

If you scroll down on google images, click an image and go back, it will just work. That's because it loads up the full page height before the images, just so the browser can do its magic. But if you scroll down, copy the link and paste it anywhere else, it won't work. Here in discourse it will. And so would in my next implementation...

I'm all forward for finding an easy solution or a simple fix that works for you here, but I don't think there is any. At this point, I'm willing to just give your money back if you're unable to wait more.


Quote for functionality in Squarespace Website
#54

Well, I got some time off today to focus on this and spent all morning trying to resolve this. In the end it didn't work out... Slowly I ended coming up with this idea, trying to use lazy loading instead of endless pagination. Two complete core rewrites. This last one (thanks to yet another web lib now being used) made code smaller and it's almost working perfectly now!

Please, do take a look: http://www.outstyled.com/new-shop/

As usual, I found a few bugs already (actually just on iPad safari and chrome), but please let me know if this is the right path, just to be sure before I try to fix those.


#55

I whole heartedly appreciate the work you have done and would not ask for my money back. Your solutions have been very creative. At this point I still think switching to Galapagos might be our best option. This option will only work if you can alter the default number of products per page...is that possible?

I am concerned about the amount of custom code and bug fixing that is necessary to fix up Supply. I am not sure what will happen when SS updates their platform/templates. I am more comfortable with a solution that is simpler. I am hopeful that switching to Galapagos will be a simpler fix. Let me know what you think.


#56

Well, I suppose you can wait then, right? Because I can't keep giving priority to this. My quote was completely off the mark and I'm not even working with that model anymore ( I've updated www.cregox.com/your-home ).

I don't know. Probably not. I'd have to dig deeper. If you want to switch templates, though, might worth it much more going with developer platform. It's way easier to customize things there.

I do give lifetime support for bug fixes and 2 years of updates (I should state that on the site), so those shouldn't worry you that much.

We came so close to a nice solution. You didn't say anything about this last one. I wouldn't like going back to a old style pagination, I've always found it quite dreadful...

I'd like to know what you think of how it is currently. At least on my desktop chrome it seems to be already working perfectly fine. The code is also cleaner, so fixing the bugs on mobile (and now I noticed, desktop safari as well) shouldn't take much longer.


#57

I looked at the latest new-shop on my desktop and did not love the initial loading sequence. It looked like every product page was stacked on top of each other, but when it was finally done it looked nice. It also gets blurry when I scroll down the page. The page history worked well when I used the back arrow.

Do you think we should continue with Supply and not switch to Galapagos? You are the expert.


#58

On a better thought, how about this: I'll just give up on making this a job (saying this because I'm not sure you've read my edit there). I could eventually take a project like this and turn it into my own featured open source project. From the past 6 months, I can't remember a single job that required to build something to fix a completely broken behaviour on squarespace.

I guess that's why I was already so dragged into this to begin with anyway! stuck_out_tongue_winking_eye

What matters most to you from my decision there is I'll try to focus more on it and probably end up much earlier than if I kept my previous mindset.

So...

I've fixed (actually hide) the loading sequence (which was one bug I had seen, just not on my chrome), and I can remove the "blurred" images (actually low resolution ones) if you insist. But keep in mind Google just release a new photos on Google I/O just yesterday and coincidentally that blurring is one nice feature it has!

You see, loading quality images take resources. Loading smaller ones takes much much less, makes things faster. Instead of the low-res img I could put nothing or leave the product price there, but neither will look as cool as this. At least technically speaking. I'm not so much expert in designing arts and layout, but I can understand why you might not like this. smile

Thanks to the lazy loading, I fairly easily implemented the paging number I've mentioned in the video and many times since the beginning. Then added that into the shop item page, so even the < BACK button will go back to the proper scrolled place (once we implement it there).

Right now, I'm only missing reloading and 1 bug I can see only on mobile, which keeps scrolling back to top. I'm also still not satisfied with loading speed on my android, which maybe improved by removing the small res images after all. Only reason I haven't tried it yet is, as so many things here, it's not that simple. stuck_out_tongue


#59

It sounds like you think we should continue fixing/debugging Supply. Not switch to Galapagos. Shall I get the Developer platform set up? If so, how do I do that?


#60

Fixing/debugging/improving. Mostly just been improving. I've mentioned the dev platform because you've mentioned switching. But I think right now switching templates would be unnecessary and have more overhead than benefits. And I can't seen to reproduce the bug anymore.

How do you like it now?