2
\$\begingroup\$

I made infinite scroll for a currency (in the code below: valute) list. The currency list is fetched via an AJAX-request from a remote server. After it starts the script displays 10 records. After the user scrolls it adds another set of records into the page.

window.onscroll = function () {
    var B = document.body, 
            DE = document.documentElement,
            O = Math.min (B.clientHeight, DE.clientHeight); 

    if (!O) {
        O = B.clientHeight;
    }

    var S = Math.max (B.scrollTop, DE.scrollTop),
            C = Math.max (B.scrollHeight, DE.scrollHeight);

    if (O + S == C) {
        console.log('add');
        start = step;
        step += step;
        constructValute(start, step);
    }   
}

var start = 0, 
        step = 10;
var valuteArr = [],
        valuteArrLength = 0;

function constructValute(start, end) {
    var bodyEl = document.getElementById('body'),
            valuteArrLength = valuteArr.length;

    for(i = start; i < end; i++) {
        var tpl = document.getElementById('item');
      var itemEl = document.createElement('div');     

      if(i < valuteArrLength) {
          var CharCode = valuteArr[i].CharCode;
          var Name = valuteArr[i].Name;
          var Value = valuteArr[i].Value;

            tpl_ = tpl.innerHTML.replace('__CharCode__', CharCode)
                                                    .replace('__Name__', Name)
                                                    .replace('__Value__', Value);

          itemEl.className = 'item';
          itemEl.innerHTML = tpl_;
          bodyEl.appendChild(itemEl);
      } else {
        console.log('stopeed add')
        break;
      }

    }
};

function ajaxReq() {
    var this_ = this;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://www.cbr-xml-daily.ru/daily_json.js');
    xhr.onload = function() {
    if (xhr.status === 200) {
        var responseText = xhr.responseText;
        var responseTextParsed = JSON.parse(xhr.responseText);
        var vauteList = responseTextParsed.Valute;

      //console.log('responseTextParsed is ', JSON.parse(xhr.responseText));
      console.log('valute list is ', vauteList);

      var valuteArr = [],
            i = 0;

        for(var prop in vauteList) {
            valuteArr[i] = vauteList[prop];
            ++i;              
            };

            valuteArrLength = valuteArr.length;
            console.log(valuteArrLength, valuteArr);

            this_.valuteArr = valuteArr;
      constructValute(0, step);
    }
    else {
      console.log('Request failed.  Returned status of ' + xhr.status);
    }
    };
    xhr.send(); 
};

ajaxReq();
body{
    padding: 0px;
}

    .item{
        width: 100%;
        margin-bottom: 10px;
    }

        .item-inner{
            border: 1px solid #ccc;
            padding: 10px;
            overflow: hidden;
        }

            .left{
                width: 90px;
                height: 90px;
                float: left;
                font-size: 2em;
                font-weight: bold;
                display: flex;
                flex-wrap: wrap;
                justify-content: center;
                align-items: center;                
            }

            .right{
                width: calc(100% - 100px);
                float: right;
                display: flex;
                flex-wrap: wrap;
                justify-content: flex-start;
                align-items: center;        
                min-height: 90px;       
            }

                .line{
                    width: 100%;
                }
<body id="body">
        <script id="item" type="text/template">
                <div class="item-inner">
                    <div class="left">__CharCode__</div>
                    <div class="right">
                            <div class="line name">__Name__</div>
                            <div class="line value">__Value__</div>
                    </div>
                </div>
        </script>
</body>

PLUNKER

\$\endgroup\$
3
\$\begingroup\$

window.onscroll should be throttled. See more info here.


if (xhr.status === 200) {
    /* main code*/
} else {
    /*error handling*/
}

This could be improved like this:

if (xhr.status !== 200) {
    /*error handling*/
    return;
}
/* main code*/

The same is true for if(i < valuteArrLength)

Read more about that here.


My personal opinion: one letter variable names are hard to follow.

\$\endgroup\$
1
\$\begingroup\$

First, I suggest reading this article. It has great advice about speeding up javascript code that interacts with the HTML elements of the page.

DOM lookups and variables

Taking the advice of that article mentioned above, put the code in an IIFE so the variables declared will only be available to the functions in this code, and avoid conflicting with other variables elsewhere.

Then wait for the DOM to load by using document.addEventListener() 1 to subscribe to the DOMContentLoaded event. Once that has happened, run the queries to get the elements needed - e.g. document.body, document.getElementById('item') (especially since that doesn't need to happen inside the for loop within constructValute()). Also, because the <body> tag has the id attribute set to body, document.getElementById('body') is equivalent to document.body so that extra variable can be eliminated.

(function() {
    var bodyEl, tpl;
    document.addEventListener('DOMContentLoaded', function() {
      bodyEl = document.body;//document.getElementById('body');
      tpl = document.getElementById('item');
      //..rest of calls once DOM has loaded: add scroll handler, call ajaxReq()
    });

    //other functions like constructValute, ajaxReq
}());

Adding Scroll handler

One can use window.addEventListener('scroll') also to add a scroll handler - that can also go in the callback to theDOMContentLoaded event. This allows for multiple functions to be called during a scroll, unlike assigning window.onscroll.

window.addEventListener('scroll', function(scrollEvent) {
    var B = bodyEl,
      DE = document.documentElement,
      O = Math.min(B.clientHeight, DE.clientHeight);
});

Adding items from the AJAX response to the array

This code:

var valuteArr = [],
        i = 0;

    for(var prop in vauteList) {
        valuteArr[i] = vauteList[prop];
        ++i;              
        };

Could be simplified using Object.values(), Array.prototype.forEach() and Array.prototype.push(), thus reducing the need for the iterator value i. Actually, I removed the variable valueArr inside the callback function and referenced the one outside the callback function, thus reducing the need for that extra variable, as well as _this.

Object.values(vauteList).forEach(function(obj) {
    valuteArr.push(obj);
});

See updated plunker here.

1 Note - not supported by IE 8 or earlier - read more about using attachEvent in that case here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.