Slow performance rendering in client templating engine (Rivets.js) - javascript

I'm rendering an array of of about 1000 objects. The html bindings are very heavy (see below). It's taking about 5 seconds to rivets.bind().
Any suggestions on improving performance? I don't think I can afford to bind in chunks as I'm using a pagination/sorting library in conjuction that needs the entire array in order to sort/paginate.
Here is my HTML for each object (tracks):
<div rv-each-track="tracks" class="track-row row has-hover" rv-download-url="track.direct_path.download_path" rv-api-key="track.track.apikey" rv-media-url="track.direct_path.audio" rv-track-title="track.track.name" rv-wave-data="track.direct_path.wave_default" rv-wave-progress-data="track.direct_path.wave_progress">
<div class="mobile-margin">
<div class="track-hover desktop-only">
<div class="hover-play icon-play inline-play"></div>
<div class="hover-title">{track.track.name}<span rv-class="track.track.staff_pick | staffPickClass" data-toggle="tooltip" data-original-title="Staff Pick"></span></div>
<div class="hover-links">
<div class="item hamburger holds-tooltip main-hover-item icon-hamburger" data-toggle="tooltip" data-original-title="Alternate Versions"></div>
<div class="item share main-hover-item popover-button icon-share" data-target="#not-ready-popover"><div class="tooltip-holder holds-tooltip" data-toggle="tooltip" data-original-title="Share Track"></div></div>
<div class="item playlist icon-playlist-add popover-button holds-tooltip main-hover-item" data-target="#playlist-popover" data-toggle="tooltip" data-original-title="Add to Playlist"></div>
<div class="item download icon-download holds-tooltip main-hover-item" data-toggle="tooltip" data-original-title="Download Track"></div>
<div class="item cart last icon-cart-plus holds-tooltip main-hover-item popover-button" data-target="#not-ready-popover" data-toggle="tooltip" data-original-title="Add to Cart"></div>
<div class="item remove last icon-x holds-tooltip main-hover-item" data-toggle="tooltip" data-original-title="Remove Track" rv-data-delete-track-id="track.track.apikey"></div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
<div class="track-variations">
<div rv-each-variation="track.variations.tracks" class="row variation-row" rv-data-track-id="track.track.apikey" rv-api-key="variation.track.apikey" rv-media-url="variation.direct_path.audio" rv-track-title="variation.track.name" rv-wave-data="variation.direct_path.wave_default" rv-wave-progress-data="variation.direct_path.wave_progress">
<div class="col-md-8 variation-title">{variation.track.name}</div>
<div class="col-md-2 variation-length">{variation.track.tracklength}</div>
<div class="track-hover variation">
<div class="hover-play icon-play inline-play"></div>
<div class="hover-title"><a class="track-link">{variation.track.name}</a></div>
<div class="hover-links">
<div class="item share popover-button icon-share" data-target="#not-ready-popover"><div class="tooltip-holder holds-tooltip" data-toggle="tooltip" data-original-title="Share Track"></div></div>
<div class="item playlist popover-button icon-playlist-add" data-target="#playlist-popover" data-toggle="tooltip" data-original-title="Add to Playlist" data-placement="left"></div>
<div class="item download icon-download" rv-data-media-url="track.direct_path.download_path" data-toggle="tooltip" data-original-title="Download Track" data-placement="left"></div>
<div class="item cart last icon-cart-plus holds-tooltip popover-button" data-target="#not-ready-popover" data-toggle="tooltip" data-original-title="Add to Cart"></div>
<div class="item last remove main-hover-item icon-x"></div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</div>
<div class="no-variations" rv-hide="track.variations.tracks | shouldHideNoVariations">There are no alternate versions of this track.</div>
</div>
</div>
<div class="col-md-4 first-title desktop-only"><a class="offset-left track-title-link track-link" href="">{track.track.name}</a><span rv-class="track.track.staff_pick | staffPickClass" data-toggle="tooltip" data-original-title="Staff Pick"></span></span></div>
<div class="col-md-3 genre desktop-only"><span class="offset-left">{track.genre}</span></div>
<div class="col-md-2 mood desktop-only"><span class="offset-left">{track.mood}</span></div>
<div class="col-md-2 canvas desktop-only"><div class="mini-wave offset-left" rv-style-background-image="track.direct_path.wave_canvas"></div></div>
<div class="col-md-1 last-title duration desktop-only"><span>{track.track.tracklength}</span></div>
<div class="col-md-1 last-title last-played pull-right desktop-only">{track.lastPlayed}</div>
<div class="mobile-play icon-play pull-left mobile-only inline-play"></div>
<div class="mobile-track-title mobile-only track-row-item-margin"><div class="track-title-link">{track.track.name}</div><span rv-class="track.track.staff_pick | staffPickClass"></span></div>
<div class="mobile-track-buttons pull-right">
<div class="pull-right mobile-only mobile-button mobile-track-menu-button left-margin icon-plus"></div>
<div class="pull-right mobile-only mobile-button mobile-variations-button icon-hamburger"></div>
</div>
<div class="is-staff-pick hidden">{track.track.staff_pick | staffPickValue}</div>
<div class="instrument hidden">{track.instrument}</div>
<div class="industry hidden">{track.industry}</div>
<div class="tempo hidden">{track.tempo}</div>
<div class="aggregated-terms hidden">{track.tag_list} {track.track.name}</div>
<div class="date-last-played hidden">{track.dateLastPlayed}</div>
<div class="clearfix"></div>
</div>
<div class="track-variations mobile-only">
<div rv-each-variation="track.variations.tracks" class="row variation-row" rv-api-key="track.track.apikey" rv-media-url="variation.direct_path.audio" rv-track-title="variation.track.name">
<div class="mobile-margin">
<div class="col-md-8 variation-title desktop-only">{variation.track.name}</div>
<div class="col-md-2 variation-length desktop-only">{variation.track.tracklength}</div>
<div class="track-hover variation">
<div class="hover-play icon-play inline-play"></div>
<div class="hover-title">{variation.track.name}</div>
<div class="hover-links">
<div class="item share popover-button icon-share" data-target="#not-ready-popover"><div class="tooltip-holder holds-tooltip" data-toggle="tooltip" data-original-title="Share Track"></div></div>
<div class="item playlist popover-button icon-playlist-add" data-target="#playlist-popover" data-toggle="tooltip" data-original-title="Add to Playlist" data-placement="left"></div>
<div class="item download icon-download" data-toggle="tooltip" data-original-title="Download Track" data-placement="left"></div>
<div class="item cart last icon-cart-plus holds-tooltip popover-button" data-target="#not-ready-popover" data-toggle="tooltip" data-original-title="Add to Cart"></div>
<div class="item last remove main-hover-item icon-x"></div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
<div class="mobile-play icon-play pull-left mobile-only inline-play"></div>
<div class="mobile-track-title mobile-only track-row-item-margin"><div class="track-title-link">{variation.track.name}</div></div>
<div class="mobile-track-buttons pull-right">
<div class="pull-right mobile-only mobile-button mobile-track-menu-button left-margin icon-plus"></div>
</div>
</div>
</div>
<div class="no-variations" rv-hide="track.variations.tracks | shouldHideNoVariations">There are no alternate versions of this track.</div>
</div>

Do not do rivets events example: rv-click which will degrade your performance because you will be passing your entire view for the callback method.
DO not pass entire view to the rivets.bind()
pass only the necessary models and do it.
If it is possible first bind 100 elements and then if user scrolled half of the page bind again 100 elements which will improve your performance for sure.
I did the below changes in binders to make it run faster even in lower end mobile devices as well.
rivets.binders.text = function(el, value) {
if (el.textContent != null) {
return el.textContent;
}
else {
return el.innerText;
}
};

I've come to the the conclusion that yes, there are minor performance improvements that I could potentially implement for binding 1000+ (large html) objects to the DOM using Rivets. However, the root issue is the fact that I'm trying to bind 1000+ rivets into the DOM at once and that is going to be inherently slow using any technique (I've tested with React, jQuery, Rivets, etc...).
The solution to this problem is to simply find another way. I've chosen to pre-render the html on the server and serve it up through an API response. This cut the page load time down from ~5s to ~1s.

Related

Cannot set .color property in JS

<button id="change_button" class="btn btn-primary" onclick="ColorMe()">CLICK ME</button>
<div class="container">
<div class="row">
<div class="col-md-4 col-sm-4">
<div class="grid_element">
<div class="title">
COLOR IS:
</div>
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="grid_element">
<div class="title">
COLOR IS:
</div>
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="grid_element">
<div class="title">
COLOR IS:
</div>
</div>
</div>
</div>
Clicking a button is supposed to color all the elements of class "grid_element" into red but in never happens.
function ColorMe() {
document.getElementsByClassName("grid_element").style.color = ("red");
}
The problem is said to be Cannot set property 'color' of undefined
at ColorMe (js.js:2) but I know it worked in the same way many times before.
The problem is that you are attempting to use the .style property on the collection of elements found by .getElementsByClassName() instead of on each of the elements within the collection.
Also (FYI), .getElementsByClassName() returns a "live" node list, which causes the entire DOM to be re-scanned every time you access the node list variable and that can impact performance quite a bit. There are limited use cases for that, so you probably want a "static" node list more often than not. For that, use .querySelectorAll().
function ColorMe() {
// Get all the matching elements into a JavaScript Array
var elements = Array.prototype.slice.call(document.querySelectorAll(".grid_element"));
// Loop over each element....
elements.forEach(function(el){
el.style.color = "red"; // Adjust the element's style
});
}
<button id="change_button" class="btn btn-primary" onclick="ColorMe()">CLICK ME</button>
<div class="container">
<div class="row">
<div class="col-md-4 col-sm-4">
<div class="grid_element">
<div class="title">
COLOR IS:
</div>
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="grid_element">
<div class="title">
COLOR IS:
</div>
</div>
</div>
<div class="col-md-4 col-sm-4">
<div class="grid_element">
<div class="title">
COLOR IS:
</div>
</div>
</div>
</div>

How to change the Checkbox icon to behave like **indeterminate** with "+" and "-" Symbols

I have checkbox with its original behaviour. I wanted to add + and - symbols to it while expanding and collapsing those checkbox.
Can any one please tell me how can I achieve this ?
Following is my Code in jade:
.form-group
.checkbox#some-checkbox(style="margin-left: 10px;")
label(data-toggle='collapse', data-target='#collapseOne', aria-expanded='false', aria-controls='collapseOne')
input(type='checkbox')
| My Name
#collapseOne.collapse(aria-expanded='false')
.well1
.row
.col-sm-12.col-lg-12
.nutrition-category
.row.header3.margin-left-10
.row.paragraph
.col-xs-6(style="font-size: 18px;") New Name
Non Jade (HTML) Code:
<div class="form-group">
<div class="checkbox" id="some-checkbox" style="margin-left: 10px">
<label data-toggle="collapse" data-target="#collapseOne" aria-
expanded="false" aria-controls="collapseOne">
<input type="checkbox"/> My Name
</label>
</div>
</div>
<div class="collapse" id="collapseOne" aria-expanded="false">
<div class="well1">
<div class="row">
<div class="col-sm-12 col-lg-12">
<div class="nutrition-category">
<div class="row header3 margin-left-10">
<div class="row paragraph">
<div class="col-xs-6" style="font-size: 18px"> New
Name</div>
</div>
</div>
</div>
</div>
</div>
and here is the javascript that i have used for it:
script(type='text/javascript').
$(document).ready(function() {
$("#some-checkbox").prop("indeterminate", true);
});

How can I locate element for ecom application , where I have a product listing page , below is HTML:

I am new in webdriver automation field. I am trying to click on the first product in Product listing page but I am unable to locate any product element in order to click on it. Kindly help. Already tried google and stack overflow for answers but couldn't find one to solve my issue.
My code:
<div class="small-6 medium-4 large-3 columns category-product cat-grid grid-view clear-both" data-name="Zivame Bandage Moderate Pushup Strapless Bra-Black" data-rating="" data-ptype="Bras" data-brand="Zivame" data-sku="B65707-Black" data-product-id="174254"
style="height: 545px;">
<div class="image-wrapper" data-price="995" data-name="Zivame Bandage Moderate Pushup Strapless Bra-Black" title="Zivame `enter code here`Bandage Moderate Pushup Strapless Bra-Black">`enter code here`
<div class="front pos-relative">
<a target="_blank" href="/zivame-bandage-moderate-pushup-strapless-bra-black.html?trksrc=category&trkid=Bras">
<img class="act-place lazy" data-small="//cdn.zivame.com/media/zcmsimages/configimages/B65707-Black/1_small.jpg" data-original="//cdn.zivame.com/media/zcmsimages/configimages/B65707-Black/1_medium.jpg" src="//cdn.zivame.com/media/zcmsimages/configimages/B65707-Black/1_medium.jpg"
alt="Zivame Bandage Moderate Pushup Strapless Bra-Black" style="display: inline-block;">
</a>
<div class="product-name">
</div>
<div class="more-on icon-chevron-down pointer show-for-small-down"></div>
<div class="mobile-controls show-for-small-down">
<div class="row product-details">
<div class="row">
<div class="row">
<div class="large-12 medium-12 small-12 columns more-actions show-for-medium-up">
<div class="check-size left text-center pointer" title="check sizes">
<i class="sel-product-color left pd-l10 pointer icon-palette" title="More colors in this"></i>
<span class="fs-10 left color-count">1</span>
<i class="show-similar left pd-l10 pointer icon-layers" title="More like this"></i>
<div class="add-to-cart-btn mr-r10">
<span class="shortlist-item icon-heart left pointer" title="Add to Wishlist"></span>
<span class="add-to-cart z-uppercase left pointer" title="Add to Cart">Add to Cart</span>
</div>
<div class="fav-count fs-10 ff-rr">216 people favorited this</div>
</div>

ngRepeat doesn't display items

We're working on a e-commerce platform at my work and we use AngularJS. Yesterday we put a great amount (200+, in small quantities it works well) of products in the bag and a bug started, some items aren't listed but it is in the HTML when we inspect elements.
The following codes are what we have:
The directive:
class dSacolaItem{
constructor(){
this.restrict = 'EA';
this.templateUrl = 'views/directives/component-sacola-item.html';
this.scope = {
dirParent: '=?dSacolaItem'
};
}}
The template of the items:
<div class="row block-item" ng-repeat="(key, prod) in dirParent.data track by $index">
<div class="col-xs-12 col-sm-4 col-md-6">
<div class="box-img pull-left">
<img class="img-responsive" ng-src="images/photos/50/{{::prod.imagem}}" d-err-src="images/photos/50/0.jpg" alt="{{::prod.descricao_curta}}">
</div>
<div class="box-infos pull-left">
<h5 class="text-uppercase text-primary" ui-sref="main.produto({ idproduto: {{::prod.id_produto}}, descricao: '{{::prod.descricao_link}}' })">{{::prod.descricao_curta}}</h5>
<small>{{::prod.var1 == undefined ? 'Único' : prod.var1}} | {{::prod.var2 == undefined ? 'Único' : prod.var2}} | {{::prod.var3 == undefined ? 'Único' : prod.var3}}</small>
<button class="btn btn-default btn-xs" type="button" ng-click="dirParent.removeItem(prod.id_variacao)">
<span ng-show="dirParent.removing_prod != prod.id_variacao">remover</span><span ng-show="dirParent.removing_prod == prod.id_variacao"><i class="fa fa-refresh fa-spin"></i></span>
</button>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-1 text-center">
<div class="box-gift text-center">
<form name="fGift" ng-submit="false" novalidate>
<label class="gift-prod" ng-if="::(dirParent.configs.produto_preco_presente > 0)">
<input type="checkbox" name="presente" ng-model="prod.presente" ng-change="dirParent.setGift( key, prod.presente )">
<div>
<i class="fa fa-gift fa-3x"></i>
<small>PRESENTE</small>
<small>(R$ {{::dirParent.configs.produto_preco_presente | currency: '': 2}})</small>
</div>
</label>
</form>
</div>
</div>
<div class="col-xs-6 col-sm-2 col-md-1 text-center">
<div class="box-qtde" tooltip-placement="left" uib-tooltip="Em estoque: {{::prod.estoque}}" tooltip-enable="prod.estoque == prod.qtde">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button class="btn btn-primary" ng-click="dirParent.updateQtde('decrement', key)" ng-class="{'disabled': prod.qtde == 1}"><i class="fa fa-angle-down"></i></button>
</div>
<div class="btn-group">
<button class="btn btn-primary" ng-click="dirParent.updateQtde('increment', key)" ng-class="{'disabled': prod.estoque == prod.qtde}"><i class="fa fa-angle-up"></i></button>
</div>
</div>
<input class="form-control text-center" type="text" ng-value="prod.qtde" disabled="disabled">
<i class="fa fa-refresh fa-spin refresh-qtde" ng-style="dirParent.value_load[key]"></i>
</div>
</div>
<div class="col-xs-6 col-sm-2 box-values text-center">
<span>unitário:</span>
<h5 class="text-primary">R$ {{::prod.preco | currency: '': 2}}</h5>
</div>
<div class="col-xs-6 col-sm-2 box-values text-center">
<span>total:</span>
<h5>R$ {{prod.preco * prod.qtde | currency: '': 2}}</h5>
</div>
I tried to use one-time binding in every place that was possible, but some data needs to be updated...
And finally, how I call the directive:
<div class="shopping-items" d-sacola-item="bag"></div>
I tried to put infinite scroll but it didn't work and also went through a lot of articles trying to fix this but nothing helped.
Some prints of the problem (look to the scroll)
Begin of displayed data (scroll is in 1/3 of the page)
Item not displayed but in the HTML
Anyone with the same problem? I don't know anymore what I should do to fix it.
[add 1]: It seems only browsers that use chromium (Chrome, Opera...) have the issue. Firefox, IE, edge and wow safari 5.1 (2012 version) show everything with some hard work, but at least they display data correctly.

How to initialize dynamic fields generated with a ng-repeat?

If I have in my view this html code, generated dinamically with ng-repeat:
<div ng-repeat="item in selectedProcedures track by $index">
<span style="display:none;">{{item.id}}</span>
<div class="row" ng-repeat="item2 in item.serviceComposite.designators">
<div class="col-sm-10 col-md-10 col-xl-10">
<div>
<button ng-click="hidePartBindings{{$parent.$index}} = !hidePartBindings{{$parent.$index}}" style="background: none; border: 0; float:left; text-align:center; margin-right: 5px;"><img src="./css/themes/parsek/img/layout/caret-blue.svg"/></button>
<span id="serviceComposite{{$parent.$index}}">{{ item2.extension }}</span>
</div>
<div class="row" id="partBindings{{$parent.$index}}" ng-repeat="item4 in item.serviceComposite.partBindings" ng-show="hidePartBindings{{$parent.$index}} === false">
<div ng-repeat="item5 in item4.part.designators">
<span class="col-sm-12 col-md-12 col-xl-12">
<a style="margin-left: 3rem;" href="#item-information" class="lightbox2" ng-click="checkIfIsModified({{item5.id}}, $event)">{{ item5.extension }}</a>
</span>
</div>
</div>
</div>
</div>
</div>
How can I initialize all generated hidePartBindings{{$parent.$index}} to true in my controller?
Thanks in advance.
You could also consider a controller for each instance of your repeated item. Of course, it would not be the best thing to do if you have hundreds of items.
<div class="row" ng-repeat="item2 in item.serviceComposite.designators" ng-controller="ItemController">
If you had fewer items and wanted to go down the route of a controller for each item, it would be a simple case of setting item.hideParts = true in your item controller.

Categories