mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Adding infinite-scroll to the shopfront
For performance improvement with large data sets
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
Darkswarm.controller "ProductsCtrl", ($scope, $rootScope, Products, OrderCycle, FilterSelectorsService, Cart, Taxons, Properties) ->
|
||||
Darkswarm.controller "ProductsCtrl", ($scope, $filter, $rootScope, Products, OrderCycle, FilterSelectorsService, Cart, Taxons, Properties) ->
|
||||
$scope.Products = Products
|
||||
$scope.Cart = Cart
|
||||
$scope.query = ""
|
||||
$scope.taxonSelectors = FilterSelectorsService.createSelectors()
|
||||
$scope.propertySelectors = FilterSelectorsService.createSelectors()
|
||||
$scope.filtersActive = true
|
||||
$scope.limit = 3
|
||||
$scope.limit = 10
|
||||
$scope.order_cycle = OrderCycle.order_cycle
|
||||
|
||||
$scope.$watch "Products.loading", (newValue, oldValue) ->
|
||||
$scope.$broadcast("loadFilterSelectors") if !newValue
|
||||
|
||||
$scope.incrementLimit = ->
|
||||
if $scope.limit < Products.products.length
|
||||
$scope.limit = $scope.limit + 1
|
||||
$scope.limit += 10 if $scope.limit < Products.products.length
|
||||
|
||||
$scope.$watchGroup ['query','taxonSelectors','propertySelectors'], ->
|
||||
$scope.limit = 10
|
||||
|
||||
$scope.searchKeypress = (e)->
|
||||
code = e.keyCode || e.which
|
||||
|
||||
@@ -2,6 +2,7 @@ Darkswarm.filter 'products', (Matcher) ->
|
||||
(products, text) ->
|
||||
products ||= []
|
||||
text ?= ""
|
||||
return products if text == ""
|
||||
products.filter (product) =>
|
||||
propertiesToMatch = [product.name, product.supplier.name, product.primary_taxon.name]
|
||||
Matcher.match propertiesToMatch, text
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
/* ng-infinite-scroll - v1.0.0 - 2013-02-23 */
|
||||
var mod;mod=angular.module("infinite-scroll",[]),mod.directive("infiniteScroll",["$rootScope","$window","$timeout",function(i,n,e){return{link:function(t,l,o){var r,c,f,a;return n=angular.element(n),f=0,null!=o.infiniteScrollDistance&&t.$watch(o.infiniteScrollDistance,function(i){return f=parseInt(i,10)}),a=!0,r=!1,null!=o.infiniteScrollDisabled&&t.$watch(o.infiniteScrollDisabled,function(i){return a=!i,a&&r?(r=!1,c()):void 0}),c=function(){var e,c,u,d;return d=n.height()+n.scrollTop(),e=l.offset().top+l.height(),c=e-d,u=n.height()*f>=c,u&&a?i.$$phase?t.$eval(o.infiniteScroll):t.$apply(o.infiniteScroll):u?r=!0:void 0},n.on("scroll",c),t.$on("$destroy",function(){return n.off("scroll",c)}),e(function(){return o.infiniteScrollImmediateCheck?t.$eval(o.infiniteScrollImmediateCheck)?c():void 0:c()},0)}}}]);
|
||||
/* ng-infinite-scroll - v1.3.0 - 2016-06-30 */
|
||||
angular.module("infinite-scroll",[]).value("THROTTLE_MILLISECONDS",null).directive("infiniteScroll",["$rootScope","$window","$interval","THROTTLE_MILLISECONDS",function(a,b,c,d){return{scope:{infiniteScroll:"&",infiniteScrollContainer:"=",infiniteScrollDistance:"=",infiniteScrollDisabled:"=",infiniteScrollUseDocumentBottom:"=",infiniteScrollListenForEvent:"@"},link:function(e,f,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;return z=angular.element(b),u=null,v=null,j=null,k=null,r=!0,y=!1,x=null,i=!1,q=function(a){return a=a[0]||a,isNaN(a.offsetHeight)?a.document.documentElement.clientHeight:a.offsetHeight},s=function(a){if(a[0].getBoundingClientRect&&!a.css("none"))return a[0].getBoundingClientRect().top+t(a)},t=function(a){return a=a[0]||a,isNaN(window.pageYOffset)?a.document.documentElement.scrollTop:a.ownerDocument.defaultView.pageYOffset},p=function(){var b,d,g,h,l;return k===z?(b=q(k)+t(k[0].document.documentElement),g=s(f)+q(f)):(b=q(k),d=0,void 0!==s(k)&&(d=s(k)),g=s(f)-d+q(f)),y&&(g=q((f[0].ownerDocument||f[0].document).documentElement)),h=g-b,l=h<=q(k)*u+1,l?(j=!0,v?e.$$phase||a.$$phase?e.infiniteScroll():e.$apply(e.infiniteScroll):void 0):(i&&c.cancel(i),j=!1)},w=function(a,b){var d,e,f;return f=null,e=0,d=function(){return e=(new Date).getTime(),c.cancel(f),f=null,a.call()},function(){var g,h;return g=(new Date).getTime(),h=b-(g-e),h<=0?(c.cancel(f),f=null,e=g,a.call()):f?void 0:f=c(d,h,1)}},null!=d&&(p=w(p,d)),e.$on("$destroy",function(){if(k.unbind("scroll",p),null!=x&&(x(),x=null),i)return c.cancel(i)}),n=function(a){return u=parseFloat(a)||0},e.$watch("infiniteScrollDistance",n),n(e.infiniteScrollDistance),m=function(a){if(v=!a,v&&j)return j=!1,p()},e.$watch("infiniteScrollDisabled",m),m(e.infiniteScrollDisabled),o=function(a){return y=a},e.$watch("infiniteScrollUseDocumentBottom",o),o(e.infiniteScrollUseDocumentBottom),h=function(a){if(null!=k&&k.unbind("scroll",p),k=a,null!=a)return k.bind("scroll",p)},h(z),e.infiniteScrollListenForEvent&&(x=a.$on(e.infiniteScrollListenForEvent,p)),l=function(a){if(null!=a&&0!==a.length){if(a.nodeType&&1===a.nodeType?a=angular.element(a):"function"==typeof a.append?a=angular.element(a[a.length-1]):"string"==typeof a&&(a=angular.element(document.querySelector(a))),null!=a)return h(a);throw new Error("invalid infinite-scroll-container attribute.")}},e.$watch("infiniteScrollContainer",l),l(e.infiniteScrollContainer||[]),null!=g.infiniteScrollParent&&h(angular.element(f.parent())),null!=g.infiniteScrollImmediateCheck&&(r=e.$eval(g.infiniteScrollImmediateCheck)),i=c(function(){return r&&p(),c.cancel(i)})}}}]),"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="infinite-scroll");
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
"ng-disabled" => "!variant.on_demand && variant.count_on_hand == 0",
|
||||
name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"}
|
||||
name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
.small-5.medium-3.large-3.columns.text-right{"ng-if" => "::variant.product.group_buy"}
|
||||
|
||||
%span.bulk-input-container
|
||||
%span.bulk-input
|
||||
%input.bulk.first{type: :number,
|
||||
@@ -6,18 +7,18 @@
|
||||
integer: true,
|
||||
min: 0,
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
placeholder: "{{'shop_variant_quantity_min' | t}}",
|
||||
placeholder: "{{::'shop_variant_quantity_min' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.count_on_hand }}",
|
||||
name: "variants[{{variant.id}}]", id: "variants_{{variant.id}}"}
|
||||
name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"}
|
||||
%span.bulk-input
|
||||
%input.bulk.second{type: :number,
|
||||
"ng-disabled" => "!variant.line_item.quantity",
|
||||
integer: true,
|
||||
min: 0,
|
||||
"ng-model" => "variant.line_item.max_quantity",
|
||||
placeholder: "{{'shop_variant_quantity_max' | t}}",
|
||||
placeholder: "{{::'shop_variant_quantity_max' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
min: "{{variant.line_item.quantity}}",
|
||||
name: "variant_attributes[{{variant.id}}][max_quantity]",
|
||||
id: "variants_{{variant.id}}_max"}
|
||||
name: "variant_attributes[{{::variant.id}}][max_quantity]",
|
||||
id: "variants_{{::variant.id}}_max"}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
.variants.row
|
||||
.small-12.medium-4.large-4.columns.variant-name
|
||||
.table-cell
|
||||
.inline {{ variant.name_to_display }}
|
||||
.inline {{ ::variant.name_to_display }}
|
||||
.bulk-buy.inline{"ng-if" => "::variant.product.group_buy"}
|
||||
%i.ofn-i_056-bulk><
|
||||
%em><
|
||||
\ {{'bulk' | t}}
|
||||
\ {{::'bulk' | t}}
|
||||
|
||||
%ng-include{src: "'partials/shop_variant_no_group_buy.html'"}
|
||||
%ng-include{src: "'partials/shop_variant_with_group_buy.html'"}
|
||||
|
||||
.small-3.medium-1.large-1.columns.variant-unit
|
||||
.table-cell
|
||||
%em {{ variant.unit_to_display }}
|
||||
%em {{ ::variant.unit_to_display }}
|
||||
|
||||
.small-4.medium-2.large-2.columns.variant-price
|
||||
.table-cell.price
|
||||
%i.ofn-i_009-close
|
||||
{{ variant.price_with_fees | localizeCurrency }}
|
||||
{{ ::variant.price_with_fees | localizeCurrency }}
|
||||
|
||||
-# Now in a template in app/assets/javascripts/templates !
|
||||
%price-breakdown{"price-breakdown" => "_", variant: "variant",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.footer-pad.small-12.columns
|
||||
%products{"ng-controller" => "ProductsCtrl", "ng-show" => "order_cycle.order_cycle_id != null", "ng-cloak" => true,
|
||||
"infinite-scroll" => "incrementLimit()", "infinite-scroll-distance" => "1"}
|
||||
%products{"ng-controller" => "ProductsCtrl", "ng-show" => "order_cycle.order_cycle_id != null", "ng-cloak" => true }
|
||||
|
||||
// TODO: Needs an ng-show to slide content down
|
||||
.row.animate-slide{ "ng-show" => "query || appliedPropertiesList() || appliedTaxonsList()" }
|
||||
@@ -29,10 +28,10 @@
|
||||
.small-12.medium-6.large-6.large-offset-1.columns
|
||||
= render partial: "shop/products/filters"
|
||||
|
||||
%div.pad-top
|
||||
%product.animate-repeat{"ng-controller" => "ProductNodeCtrl", "ng-repeat" => "product in filteredProducts = (Products.products | products:query | taxons:activeTaxons | properties: activeProperties) track by product.id ", "id" => "product-{{ product.id }}"}
|
||||
%div.pad-top{ "infinite-scroll" => "incrementLimit()", "infinite-scroll-distance" => "1", "inifinite-scroll-disabled" => '{{filteredProducts.length <= limit}}' }
|
||||
%product.animate-repeat{"ng-controller" => "ProductNodeCtrl", "ng-repeat" => "product in filteredProducts = (Products.products | products:query | taxons:activeTaxons | properties: activeProperties) | limitTo:limit track by product.id ", "id" => "product-{{ product.id }}"}
|
||||
= render "shop/products/summary"
|
||||
%shop-variant{variant: 'product.master', "ng-if" => "::!product.hasVariants", "id" => "variant-{{ product.master.id }}"}
|
||||
-# %shop-variant{variant: 'product.master', "ng-if" => "::!product.hasVariants", "id" => "variant-{{ product.master.id }}"}
|
||||
%shop-variant{variant: 'variant', "ng-repeat" => "variant in product.variants track by variant.id", "id" => "variant-{{ variant.id }}", "ng-class" => "{'out-of-stock': !variant.on_demand && variant.count_on_hand == 0}"}
|
||||
|
||||
%product{"ng-show" => "Products.loading"}
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
%span{"ng-bind" => "::enterprise.name"}
|
||||
.small-2.medium-2.large-1.columns.text-center
|
||||
.taxon-flag
|
||||
%render-svg{path: "{{product.primary_taxon.icon}}"}
|
||||
%render-svg{path: "{{::product.primary_taxon.icon}}"}
|
||||
|
||||
@@ -30,9 +30,9 @@ describe 'ProductsCtrl', ->
|
||||
it "increments the limit up to the number of products", ->
|
||||
scope.limit = 0
|
||||
scope.incrementLimit()
|
||||
expect(scope.limit).toEqual 1
|
||||
expect(scope.limit).toEqual 10
|
||||
scope.incrementLimit()
|
||||
expect(scope.limit).toEqual 1
|
||||
expect(scope.limit).toEqual 10
|
||||
|
||||
it "blocks keypresses on code 13", ->
|
||||
event =
|
||||
|
||||
Reference in New Issue
Block a user