luis-almeida / unveil

A very lightweight jQuery plugin to lazy load images
4.16k stars 676 forks source link

Please help - Why do only half my images lazy load while the rest don't load at all? #121

Open ajsingh007 opened 7 years ago

ajsingh007 commented 7 years ago

Edit: I gave up and threw this in. Whatever. $("img.sgtBtn").trigger("unveil");

Live example at: http://www.nba.com/kings/sgt-dev

I have team logos in these elements and they lazy load just fine: <img data-class="lazy" data-src="http://stats.nba.com/media/img/teams/logos/lac_logo.svg">

I have default buttons in these elements and they won't load. Why?? <img data-class="lazy" class="sgtBtn" data-src="http://i.cdn.turner.com/drp/nba/kings/sites/default/files/default_btn.png">

This is the jQuery I'm using: $("img[data-class='lazy']").unveil();

I have attached the source of the page. Please help!!

Full source code visible below:

<!-- LINKS TO STYLESHEETS, GOOGLE FONTS -->

<!-- STYLE -->

<style type="text/css">

    @font-face {
          font-family:'DinBlack';src:url('http://www.nba.com/.element/media/2.0/teamsites/kings/fonts/din-black-webfont.woff');
        }

    @font-face {
              font-family:'DinBold';src:url('http://www.nba.com/.element/media/2.0/teamsites/kings/fonts/din-bold-webfont.woff');
            }

    @font-face {
              font-family:'DinRegular';src:url('http://www.nba.com/.element/media/2.0/teamsites/kings/fonts/din-regular-webfont.woff');
            }

    @font-face {
              font-family:'DinMedium';src:url('http://www.nba.com/.element/media/2.0/teamsites/kings/fonts/din-medium-webfont.woff');
            }

    @font-face {
              font-family:'DinLight';src:url('http://www.nba.com/.element/media/2.0/teamsites/kings/fonts/din-light-webfont.woff');
            }

    @font-face {
              font-family:'industryBold';src:url('http://i.cdn.turner.com/nba/nba/.element/media/2.0/teamsites/kings/KINGSDIGITAL-SYNC/industryFontWoff/KingsIndustry-Bold.WOFF');
            }

    /*.not-front #content {
        background: transparent;
        max-width: 100%;
        width: 100%;
    }

    .panels-flexible-region {
        width: 100%;
    }*/

    div#listContainer {
        width: 101%;
        margin: 0 auto;
        display: block;
    }

    ul#gamesList {
        padding: 0;
    }

    li.matchup {
        list-style-type: none;
        border-bottom: 3px solid #797676;
        display: flex;
        justify-content: space-between;
    }

    .dateBox, .logoBox, .teamBox, .priceBox, .ticketBox {
        display: inline-block;
        width: 18%;
        align-self: center;
        text-align: left;
    }

    .day, .monthDayNum, .time, .promotion, .oppCity, .oppName, .price {
        display: block;
    }

        .day, .time, .oppCity {
            font-family: 'DinMedium';
            text-transform: uppercase;
            color: #797676;
            font-size: 1.75vw;
        }

        .monthDayNum, .oppName {
            font-size: 3vw;
            font-family: 'DinMedium';
            text-transform: uppercase;
        }

        .promotion, .from {
            font-family: 'DinBlack';
            text-transform: uppercase;
            font-size: 1.25vw;
        }

        .price {
            font-size: 3.5vw;
            font-family: 'DinMedium';
            text-transform: uppercase;
        }

    /*.logoBox {
        width: 150px;
    }*/

    .hide {
        display: none;
    }

    /*BEGIN BACK TO TOP CSS*/

        /*back to top button css*/

        .cd-container {
          width: 90%;
          max-width: 768px;
          margin: 2em auto;
        }
        .cd-container::after {
          /* clearfix */
          content: '';
          display: table;
          clear: both;
        }

        .cd-top {
              display: inline-block;
              height: 40px;
              width: 40px;
              position: fixed;
              bottom: 40px;
              right: 10px;
              box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
              /* image replacement properties */
              overflow: hidden;
              text-indent: 100%;
              white-space: nowrap;
              background: rgba(232, 98, 86, 0.8) url(http://codyhouse.co/demo/back-to-top/img/cd-top-arrow.svg) no-repeat center 50%;
              visibility: hidden;
              opacity: 0;
              -webkit-transition: opacity .3s 0s, visibility 0s .3s;
              -moz-transition: opacity .3s 0s, visibility 0s .3s;
              transition: opacity .3s 0s, visibility 0s .3s;
            }
            .cd-top.cd-is-visible, .cd-top.cd-fade-out, .no-touch .cd-top:hover {
              -webkit-transition: opacity .3s 0s, visibility 0s 0s;
              -moz-transition: opacity .3s 0s, visibility 0s 0s;
              transition: opacity .3s 0s, visibility 0s 0s;
            }
            .cd-top.cd-is-visible {
              /* the button becomes visible */
              visibility: visible;
              opacity: 1;
            }
            .cd-top.cd-fade-out {
              /* if the user keeps scrolling down, the button is out of focus and becomes less visible */
              opacity: .5;
            }
            .no-touch .cd-top:hover {
              background-color: #e86256;
              opacity: 1;
            }
            @media only screen and (min-width: 768px) {
              .cd-top {
                right: 20px;
                bottom: 20px;
              }
            }
            @media only screen and (min-width: 1024px) {
              .cd-top {
                height: 60px;
                width: 60px;
                right: 30px;
                bottom: 30px;
              }
            }

    /*END BACK TO TOP BUTTON CSS*/

    /*MEDIA QUERIES*/

    @media screen and (min-width: 1170px) {
        div.logoBox > img {
            height: 140px;
        }

        .dateBox {
            padding-left: 50px;
        }

        .priceBox {
            padding-left: 70px;
        }

        .monthDayNum, .oppName {
            font-size: 38px;
        }

        .day, .time, .oppCity {
            font-size: 22px;
        }

        .promotion, .from {
            font-size: 16px;
        }

        .price {
            font-size: 58px;
            line-height: 50px;
        }

        span.oppName {
            line-height: 28px;
        }

    }

    @media screen and (max-width: 1169px) {
        div.logoBox > img {
            height: 140px;
        }

        .dateBox {
            padding-left: 50px;
        }

        .priceBox {
            padding-left: 70px;
        }

        .monthDayNum, .oppName {
            font-size: 38px;
        }

        .day, .time, .oppCity {
            font-size: 22px;
        }

        .promotion, .from {
            font-size: 16px;
        }

        .price {
            font-size: 58px;
            line-height: 50px;
        }

        span.oppName {
            line-height: 28px;
        }

    }

    @media screen and (max-width: 1000px) {
        .dateBox {
            padding-left: 10px;
        }

        .ticketBox {
            text-align: right;
        }

        .priceBox {
            padding-left: 80px;
        }

        img.sgtBtn {
            width: 70%;
        }

        .monthDayNum, .oppName {
            font-size: 34px;
        }

        .price {
            font-size: 52px;
        }
    }

    @media screen and (max-width: 850px) {

        div.logoBox > img {
            height: 125px;
        }

        .day, .time, .oppCity {
            font-size: 18px;
            letter-spacing: -1px;
        }

        span.price {
            letter-spacing: -3px;
            font-size: 40px;
        }

        .promotion, .from {
            font-size: 14px;
        }

        .oppName {
            font-size: 30px;
        }

    }

    @media screen and (max-width: 700px) {
        .teamBox {
            display: none !important;
        }

        .dateBox, .logoBox, .teamBox, .priceBox, .ticketBox {
            width: 23%;
        }

        .priceBox {
            padding-left: 60px;
        }
    }

    @media screen and (max-width: 545px) {
        .monthDayNum {
            font-size: 30px;
            letter-spacing: -1px;
        }

        .priceBox {
            padding-left: 35px;
        }

        .logoBox {
            padding: 0px 0px 0px 14px;
        }

        img.sgtBtn {
            width: 90%;
        }
    }

    @media screen and (max-width: 414px) {

        .priceBox {
            padding-left: 15px;
        }

        .dateBox {
            padding-left: 5px;
        }

        .day, .time, .oppCity {
            font-size: 15px;
            letter-spacing: -1px;
        }

        .monthDayNum {
            font-size: 20px;
        }

        span.price {
            font-size: 35px;
        }

        .logoBox {
            padding: 0px 0px 0px 4px;
        }

        img.sgtBtn {
            width: 95%;
        }

    }

</style>

<!-- HTML -->

<div id="listContainer">

    <ul id="gamesList">

    </ul>

</div>

<a href="#0" class="cd-top">Top</a>

<!-- SCRIPTS -->
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> -->
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> -->

<!-- NOTE: comment out any references to jQuery libraries before loading onto Kings.com. Okay to enable them when testing locally or on your own server -->
<script type="text/javascript" src="https://cdn.rawgit.com/datejs/Datejs/master/build/date.js"></script>

<!-- BEGIN UNVEIL -->
<script type="text/javascript">

    /**
 * jQuery Unveil
 * A very lightweight jQuery plugin to lazy load images
 * http://luis-almeida.github.com/unveil
 *
 * Licensed under the MIT license.
 * Copyright 2013 Luís Almeida
 * https://github.com/luis-almeida
 */

;(function($) {

  $.fn.unveil = function(threshold, callback) {

    var $w = $(window),
        th = threshold || 0,
        retina = window.devicePixelRatio > 1,
        attrib = retina? "data-src-retina" : "data-src",
        images = this,
        loaded;

    this.one("unveil", function() {
      var source = this.getAttribute(attrib);
      source = source || this.getAttribute("data-src");
      if (source) {
        this.setAttribute("src", source);
        if (typeof callback === "function") callback.call(this);
      }
    });

    function unveil() {
      var inview = images.filter(function() {
        var $e = $(this);
        if ($e.is(":hidden")) return;

        var wt = $w.scrollTop(),
            wb = wt + $w.height(),
            et = $e.offset().top,
            eb = et + $e.height();

        return eb >= wt - th && et <= wb + th;
      });

      loaded = inview.trigger("unveil");
      images = images.not(loaded);
    }

    $w.on("scroll.unveil resize.unveil lookup.unveil", unveil);

    unveil();

    return this;

  };

})(window.jQuery || window.Zepto);

</script>
<!-- END UNVEIL -->

<script type="text/javascript">

////Button Sources
    // Family Button Example: http://i.cdn.turner.com/drp/nba/kings/sites/default/files/promo-family.png

    // Default Button Example: http://i.cdn.turner.com/drp/nba/kings/sites/default/files/default_btn.png

    // Promo Button Example: http://i.cdn.turner.com/drp/nba/kings/sites/default/files/promo-btn.png

    (function($) { //BEGIN DRUPAL JQUERY WRAPPER

        $( document ).ready(function() { //BEGIN DOCUMENT READY

            jQuery(document).ready(function() { //BEGIN AJAX WRAPPER
                jQuery.ajax({ //BEGIN LEAGUE'S AJAX
                    type: 'GET',
                    url: 'http://data.nba.com/data/v2015/json/mobile_teams/nba/2015/teams/kings_schedule_02.json',
                    timeout: 9999,
                    dataType: 'json',
                    success: function(returnData) {
                        console.log('successfully retrieved league schedule JSON');

                        var allGames = returnData.gscd.g;

                        var homeGames = allGames.filter(function(e) {
                            return e.ac === 'Sacramento';
                        });

                        var numberOfHomeGames = Object.keys(homeGames).length;

                        var defaultBtn = 'http://i.cdn.turner.com/drp/nba/kings/sites/default/files/default_btn.png';

                        var gid = [];
                        var dayArray = [];
                        var monthArray = [];
                        var tipOffTimeArray = [];
                        var timeStampArray = [];

                        $.each(homeGames, function(index, game) {

                            gid.push(game.gid);

                            timeStampArray.push(game.htm);

                            var day = Date.parse(game.htm).toString('dddd');

                                dayArray.push(day);

                            var month = Date.parse(game.htm).toString('MMMM');

                                monthArray.push(month);

                            var monthDayNum = Date.parse(game.htm).toString('MMM d');

                            var time = Date.parse(game.htm).toString('h:mm tt');

                                tipOffTimeArray.push(time);

                            var teamAbbr = game.v.ta.toLowerCase();

                            var itemHTML = [
                                '<li class="matchup" id="',game.gid,'" data-date="',game.gdte,'" data-month="',month,'" data-day="',day,'" data-tipoff="',game.htm,'" data-opponent="',game.v.tn,'">',

                                    '<div class="dateBox">',
                                        '<span class="day">',day,'</span>',
                                        '<span class="monthDayNum">',monthDayNum,'</span>',
                                        '<span class="time">',time,'</span>',
                                    '</div>',

                                    '<div class="logoBox">',
                                        '<img data-class="lazy" data-src="http://stats.nba.com/media/img/teams/logos/',teamAbbr,'_logo.svg">',
                                    '</div>',

                                    '<div class="teamBox">',
                                        '<span class="promotion ',game.gid,'">',
                                        '</span>',
                                        '<span class="oppCity">',game.v.tc,
                                        '</span>',
                                        '<span class="oppName">',game.v.tn,
                                        '</span>',
                                    '</div>',

                                    '<div class="priceBox">',
                                        '<span class="from" style="color: red;">FROM</span>',
                                        '<span class="price"></span>',
                                    '</div>',

                                    '<div class="ticketBox">',
                                        '<div class="primaryBtn',game.gid,'">',
                                            '<a href="" target="_blank">',
                                                '<img data-class="lazy" class="sgtBtn" data-src="http://i.cdn.turner.com/drp/nba/kings/sites/default/files/default_btn.png">',
                                            '</a>',
                                        '</div>',

                                        '<div class="secondaryBtn',game.gid,'">',
                                        '</div>',

                                    '</div>',
                                '</li>'
                                ].join(''); 
                            $('ul#gamesList').append(itemHTML);
                        });

                        //BEGIN SCHEDULED UNPUBLISHING

                            var currentTime = new Date().toString('yyyy-MM-dd-HH:mm');
                            // var currentTime = Date.parse('2015-11-06T19:30:00').toString('yyyy-MM-dd-HH:mm');
                            console.log('currentTime = ' + currentTime);

                            $('li.matchup').each(function(index, listItem) {
                                var dataDate = $(listItem).data().tipoff;
                                var parsedDataDate = Date.parse(dataDate).toString('yyyy-MM-dd-HH:mm');
                                // console.log('parsedDataDate = ' + parsedDataDate);

                                if (currentTime >= parsedDataDate) {
                                    // console.log('currentTime is > parsedDataDate, adding class of "hide");
                                    // $(listItem).addClass('hide');
                                } else if (currentTime < parsedDataDate) {
                                    // console.log('currenTime is < parsedDataDate');
                                }

                            });

                        //END SCHEDULED UNPUBLISHING

                        //SPIT GAME IDs
                            // var gidToString = gid.toString();
                            // var gidByLine = gidToString.split(',').join('\n');
                            // console.log(gidByLine);

                        //SPIT DAY OF WEEK
                            // var dayArrayToString = dayArray.toString();
                            // var dayByLine = dayArrayToString.split(',').join('\n');
                            // console.log(dayByLine);

                        //SPIT MONTHS
                            // var monthArrayToString = monthArray.toString();
                            // var monthByLine = monthArrayToString.split(',').join('\n');
                            // console.log(monthByLine);

                        //SPIT TIPOFF TIMES
                            // var tipOffTimeArrayToString = tipOffTimeArray.toString();
                            // var tipOffTimeByLine = tipOffTimeArrayToString.split(',').join('\n');
                            // console.log(tipOffTimeByLine);

                        //SPIT TIMESTAMPS
                            // var timeStampArrayToString = timeStampArray.toString();
                            // var timeStampByLine = timeStampArrayToString.split(',').join('\n');
                            // console.log(timeStampByLine);

                    },
                    error: function() {
                        console.log('Error retrieving league schedule JSON');
                    }
                }); //END LEAGUE'S AJAX

                jQuery.ajax({ //BEGIN KINGS INTERNAL AJAX
                    type: 'GET',
                    url: 'https://spreadsheets.google.com/feeds/list/1zTXOjLIQ_aGtSsTlVyQP0hFMNjxpJExyDq7-L0lgESM/od6/public/values?alt=json',
                    timeout: 9999,
                    dataType: 'json',
                    success: function(returnData) {
                        console.log('Successfully retrieved Kings Internal JSON data');

                        var events = returnData.feed.entry;

                            $.each(events, function(index, link) {
                                var gameID = link.gsx$gameid.$t;
                                var defaultLinkURL = link.gsx$primaryticlink.$t;
                                var defaultLinkA = $('div.primaryBtn' + gameID).find('a');
                                $(defaultLinkA).attr('href', defaultLinkURL);
                            })

                        var messages = events.filter(function(e) {
                            return e.gsx$messageoptional.$t != '';
                        });

                            $.each(messages, function(index, message) {
                                var gameID = message.gsx$gameid.$t;         
                                var messageText = message.gsx$messageoptional.$t;
                                var spanWithGameIDClass = 'span.' +gameID;
                                $(spanWithGameIDClass).html(messageText);
                            });

                        var promos = events.filter(function(e) {
                            return e.gsx$promotion.$t != '';
                        });

                            $.each(promos, function(index, event) {
                                var gameID = event.gsx$gameid.$t;
                                var promotion = event.gsx$promotion.$t;
                                var spanWithGameIDClass = 'span.' + gameID;
                                var secondaryBtnDiv = 'div.secondaryBtn' + gameID;
                                var promoBtnLink = event.gsx$promobtnlink.$t;
                                var promoBtnImg = event.gsx$promobtnimgsrc.$t;

                                $(spanWithGameIDClass).html(promotion);
                                $(secondaryBtnDiv).html('<a href="' + promoBtnLink + '" target="_blank"><img class="sgtBtn" src="' + promoBtnImg + '"></a>');

                                var targetLi = 'li#' + gameID;
                                $(targetLi).attr('data-promo', promotion);
                            });

                        //UNVEIL
                        $("img[data-class='lazy']").unveil();
                        //UNVEIL

                    },
                    error: function() {
                        console.log('Error retrieving league schedule JSON');
                    }
                }); //END KINGS INTERNAL AJAX

                //BEGIN SB CODE 

                    (function() {

                    // CONSTANTS
                    var sid = "41";
                    var container = "#data";
                    var events = [], sections = [];
                    var lowestPriceMap;

                    // GET DATA
                    $.support.cors = true;
                    $.ajax({
                        url: "https://api.stratbridge.com/svc/prices?season=" + sid,
                        type: "GET",
                        dataType: "json",
                        success: function(prices) {
                            console.log('successfully retrieved STRATBRIDGE data');
                            var uniqueEvents = [], times = getMapKeys(getMap(prices, "start_time"));
                            for(var i=0;i<prices.length;i++) {
                                var x = prices[i];
                                x["id"] = formatDateAsKeyString(x.start_time);
                                if(uniqueEvents.indexOf(formatDateAsKeyString(x.start_time)) < 0) {
                                    uniqueEvents.push(formatDateAsKeyString(x.start_time));
                                    events.push({ id: x.id, start_time: x.start_time, opponent: x.opponent, external_event_url: x.external_event_url, event_type: x.event_type });
                                }
                            }
                            lowestPriceMap = getLowestPrice(events, getDataMatrix(prices, ["id", "price_level"]));
                            for(var i=0;i<events.length;i++) {
                                var e = events[i].id;
                                if(lowestPriceMap[e]) {
                                    events[i]["lowest_price"] = lowestPriceMap[e];
                                }
                            }

                                //////////////////////////////////////////////////////////////////////////////////////////////////
                                // NOTE: the global 'events' object is now an array of objects with the lowest price set per event
                                // console.log(events);

                                // var priceHTML = [
                                //     '<span style="color: red;">FROM</span>',
                             //     '<span class="price"></span>',
                                // ].join('');

                                $("li[data-date]").each(function() {

                                    var date = $(this).attr('data-date');

                                    // console.log(date)

                                    var index = events.map(function(el) {
                                        return el.id;
                                    }).indexOf(date);

                                    // console.log(index);

                                    // console.log(events[index].lowest_price);

                                    $('li[data-date="' + date + '"]').find("span.price").text(events[index] && events[index].lowest_price ? "$" + events[index].lowest_price : "n/a");

                                });

                                // For a map to get values by the new ISO date string key, use getMap(events, "id")
                                // Each event object still has the epoch "start_time" property for date formatting/display if needed
                                // console.log(getMap(events, "id"));
                                //////////////////////////////////////////////////////////////////////////////////////////////////

                                // showPricingTable(events);

                                var ltd = [
                                    '<img id="ltd" src="http://i.cdn.turner.com/drp/nba/kings/sites/default/files/limited.png">'
                                ].join('');

                                // var nA = $('ul.games').find('span.price:contains("n/a")').parent();
                                // $(nA).replaceWith(ltd);

                        },
                        error: function (request, status, error) {
                            console.log('Error retrieving STRATBRIDGE data');
                        }
                    });

                    var display = {
                        "start_time": { "name": "Event Time", "format": formatDate },
                        "opponent": { "name": "Opponent" },
                        "event_type": { "name": "Type" },
                        "external_event_url": { "name": "Tickets URL", "format": formatLink },
                        "lowest_price": { "name": "From...", "format": formatCur }
                    };

                    // UTILITIES
                    function getLowestPrice(events, matrix) {
                        var map = {};
                        for(var i=0;i<events.length;i++) {
                            var e = matrix[events[i].id], priceList = [], levels = getMapKeys(e);
                            for(var j=0;j<levels.length;j++) {

                                //////////////////////////////////////////////////////////////////////////////////////////////////
                                // TODO: add check that e[levels[j]].retail_available_tickets > 0
                                // Checks that the lowest price returned is from a section that still has tickets
                                // Also handle when no tickets left/event past
                                /////////////////////////////////////////////////////////////////////////////////////////////////////

                                var item = e[levels[j]];
                                //*** if(item.retail_available_tickets && item.retail_available_tickets > 20) {
                                    priceList.push(item.current_price);
                                //***}
                            }
                            // shows lowest price from list of prices for that event
                            // todo: handle use case if there are no tickets left for an event, thus no prices in this list?
                            if(priceList.length > 0) {
                                map[events[i].id] = Array.min(priceList);
                            }
                        }
                        return map;
                    }
                    function formatDate(date) {
                        var d = new Date(date);
                        var weekdays = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
                        var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
                        var h = d.getUTCHours() % 12;
                        if (h === 0) h = 12;
                        var time = h + ":" + ("0" + d.getUTCMinutes()).slice(-2) + " " + (d.getUTCHours() < 12 ? "AM" : "PM");
                        return weekdays[d.getUTCDay()] + " " + months[d.getUTCMonth()] + " " + d.getUTCDate() + "&nbsp;&nbsp;" + time;
                    }
                    function formatDateAsKeyString(date) {
                        var d = new Date(date);
                        return d.getUTCFullYear() + "-" + twoDigitNum(d.getUTCMonth()+1) + "-" + twoDigitNum(d.getUTCDate());
                    }
                    function twoDigitNum(num) {
                        return num < 10 ? "0" + num : num;
                    }
                    function formatCur(num) {
                        Math.round(num);
                        var negative = num < 0 ? "-" : "",
                        i = parseInt(num = Math.abs(+num || 0).toFixed(0), 10) + "",
                        j = (j = i.length) > 3 ? j % 3 : 0;
                        if(num > 999 && num < 1000000) {
                            num = (num/1000).toFixed(1) + "k";
                        } else if(num > 999999 && num < 1000000000) {
                            num = (num/1000000).toFixed(1) + "m";
                        }
                        return negative + "$" + num;
                    }
                    function formatLink(url) {
                        return url ? $("<a>").html("Get Tickets &#187;").attr("target","_blank").attr("href",url) : "";
                    }
                    function getMap(list, property, multivalued) {
                        var map = {};
                        for(var i=0;i<list.length;i++) {
                            var prop = list[i][property];
                            if (multivalued) {
                                if (!map[prop]) {
                                    map[prop] = [];
                                }
                                map[prop].push(list[i]);
                            } else {
                                map[prop] = list[i];
                            }
                        }
                        return map;
                    }
                    function getMapKeys(map, sort) {
                        var keys = [];
                        for(var i in map) {
                            keys.push(i);
                        }
                        return sort ? keys.sort() : keys;
                    }
                    function getDataMatrix(data, axes) {
                        var matrix = {};
                        for(var i=0;i<data.length;i++) {
                            matrix = getSubMatrix(matrix, data[i], axes);
                        }
                        return matrix;
                    }
                    function getSubMatrix(matrix, record, axes) {
                        if(axes.length == 0) {
                            return record;
                        } else {
                            if(!matrix) {
                                matrix = {};
                            }
                            matrix[record[axes[0]]] = getSubMatrix(matrix[record[axes[0]]], record, axes.slice(1));
                            return matrix;
                        }
                    }
                    Array.min = function(array) {
                        return Math.min.apply( Math, array );
                    };

                    })();

                //END SB CODE

                //BEGIN BACK TO TOP BTN

                    // browser window scroll (in pixels) after which the "back to top" link is shown
                    var offset = 300,
                        //browser window scroll (in pixels) after which the "back to top" link opacity is reduced
                        offset_opacity = 1200,
                        //duration of the top scrolling animation (in ms)
                        scroll_top_duration = 700,
                        //grab the "back to top" link
                        $back_to_top = $('.cd-top');

                    //hide or show the "back to top" link
                    $(window).scroll(function(){
                        ( $(this).scrollTop() > offset ) ? $back_to_top.addClass('cd-is-visible') : $back_to_top.removeClass('cd-is-visible cd-fade-out');
                        if( $(this).scrollTop() > offset_opacity ) { 
                            $back_to_top.addClass('cd-fade-out');
                        }
                    });

                    //smooth scroll to top
                    $back_to_top.on('click', function(event){
                        event.preventDefault();
                        $('body,html').animate({
                            scrollTop: 0 ,
                            }, scroll_top_duration
                        );
                    });

                //END BACK TO TOP BTN

            }); //END AJAX WRAPPER

        }); //END DOCUMENT READY

    })(jQuery); //END DRUPAL JQUERY WRAPPER

</script>