<commit_before>function OutageMap(mapElement,metricsElement, zoom, centerLocation) {
    this.mapElement = mapElement;
    this.zoom = zoom;
    this.centerLocation = centerLocation;
    this.centerLocation.lat = parseFloat(this.centerLocation.lat);
    this.centerLocation.lng = parseFloat(this.centerLocation.lng);
    this.map = null;
    this.data = null;
    this.infowindows = [];
    this.metricsElement = metricsElement;
    this.metricsTemplate = metricsElement.find('.metric-template').clone();
    this.overlays = [];
    this.metricsTemplate.removeClass('metric-template hide');
    this.dispatchJobInfo = {
      colors: {
        DEFAULT: '#FF0000',
        OUTAGE_REPORTED: '#FF0000',
        REPAIR_IN_PROGRESS: '#ff8c4f'
      },
      userFriendlyName: {
        OUTAGE_REPORTED: 'Outage Reported',
        REPAIR_IN_PROGRESS: 'Repair in Progress'
      }
    };
}

OutageMap.prototype = {
    init: function() {
        var _self = this;
        _self.initialized = true;
    },

    load: function() {
        var _self = this;
        if (!_self.initialized) {
            _self.init();
        }
        _self.map = new google.maps.Map(_self.mapElement[0], {
            zoom: _self.zoom,
            center: _self.centerLocation,
            mapTypeId: 'terrain'
        });

    },

    loadOutageDataFromRemote: function(id) {
        var _self = this;
        var route = null;
        if (_.isUndefined((id))) {
            route = Routing.generate('ajax_fetch_current_outage');
        } else {
            route = Routing.generate('ajax_fetch_outage', {id: id});
        }
        $.post(route).done(function(data) {
            _self.saveOutageData(data.id, data);
            _self.drawData(data);
            _self.mapElement.trigger('outage:loaded', data);
        });
    },

    saveOutageData: function(id, data) {
        sessionStorage.setItem('outage_'+ id, JSON.stringify(data));
    },

    loadOutageData: function(id) {
        var _self = this;
        _self.clearOverlays();

        if (_.isUndefined((id))) {
            _self.loadOutageDataFromRemote();
        } else {
            var data = JSON.parse(sessionStorage.getItem('outage_'+ id));
            if (!data) {
                _self.loadOutageDataFromRemote(id);
            } else {
                _self.drawData(data);
                _self.mapElement.trigger('outage:loaded', data);
            }
        }
    },

    clearOverlays: function() {
        var _self = this;
        _.each(_self.overlays, function(v)  {
            v.setMap(null);
        });
        _self.overlays = [];
    },

    drawData: function(data) {
        var _self = this;
        _self.data = data;
        _.each(data.boundaries, function(v) {
            var districtOutage = _.find(data.districtOutages, function(o) { return v.name === o.name });
            _self.overlays.push(_self.drawBoundary(v, districtOutage, v.latLng, '#3494d3', 0.2, 1));
        });
        _.each(data.dispatches, function(v) {
            var center = {lat: parseFloat(v.latitude), lng: parseFloat(v.longitude)};
            var color = _self.dispatchJobInfo.colors['DEFAULT'];
            if (!_.isUndefined(_self.dispatchJobInfo.colors[v.jobStatus])) {
              color = _self.dispatchJobInfo.colors[v.jobStatus];
            }
            _self.overlays.push(_self.drawDispatchesOutages(v, center, color, 0.5, 1, v.customerQty));
        });

        _self.displayMetrics(data);
    },

    drawBoundary: function(boundary, districtOutage, paths, color, opacity, strokeWeight) {
        var _self = this;
        var polygon = new google.maps.Polygon({
          paths: paths,
          strokeColor: EPBOutage.darkenHexColor(color),
          strokeOpacity: 1,
          strokeWeight: strokeWeight,
          fillColor: color,
          fillOpacity: opacity,
          map: _self.map
        });

        if (!_.isUndefined(districtOutage)) {
            var content = "
"+ boundary.name +"

";
            if (districtOutage.incidents) {
                content += "
Incidents: "+ districtOutage.incidents +"
";
            }
            if (districtOutage.customersAffected) {
                content += "
Customers affected "+ districtOutage.customersAffected +"
";
            }

            var bounds = new google.maps.LatLngBounds();
            _.each(paths, function(v) {
                bounds.extend(v);
            });

            var mapLabel = new MapLabel({
                text: boundary.name,
                position: bounds.getCenter(),
                map: _self.map,
                fontSize: 12,
                align: 'right'
            });

            _self.overlays.push(mapLabel);
        }

        return polygon;
    },

    drawDispatchesOutages: function(dispatch, center, color, opacity, strokeWeight, numberOfOutages) {
        var _self = this;
        if (numberOfOutages < 10) { numberOfOutages = 10; }
        var radius = Math.sqrt(numberOfOutages) * 100;
        var circle = new google.maps.Circle({
            strokeColor: EPBOutage.darkenHexColor(color),
            strokeOpacity: 1,
            strokeWeight: strokeWeight,
            fillColor: color,
            fillOpacity: opacity,
            map: _self.map,
            center: center,
            radius: radius
          });

          var jobStatus = dispatch.jobStatus;
          if (!_.isUndefined(_self.dispatchJobInfo.userFriendlyName[dispatch.jobStatus])) {
            jobStatus = _self.dispatchJobInfo.userFriendlyName[dispatch.jobStatus];
          }
        var content = "
Outage Info

Job Status: "+ jobStatus +"
"+
                "
Crew dispatched: "+ dispatch.crewQty +"
"+
                "
Customers affected "+ dispatch.customerQty +"
";

        _self.addInfowindow(circle, content, circle.getCenter());
        return circle;
    },

    addInfowindow: function(object, content, position) {
        var _self = this;
        var infoWindow = new google.maps.InfoWindow({
            content: content
        });
        var openTimeout = null;
        var closeTimeout = null;

        object.addListener('mouseover', function () {
            if (!_.isNull(openTimeout)) {
                clearTimeout(openTimeout);
            }
            if (!_.isNull(closeTimeout)) {
                clearTimeout(closeTimeout);
            }
            openTimeout = setTimeout(function() {
                _.each(_self.infowindows, function(v) {
                    v.close();
                });
                infoWindow.open(_self.map, object);
                infoWindow.setPosition(position);
            }, 500);

        });

        object.addListener('mouseout', function() {
            if (!_.isNull(closeTimeout)) {
                clearTimeout(closeTimeout);
            }
            closeTimeout = setTimeout(function() {
                infoWindow.close();
            }, 1000);
        });

        //add infowindows to the global space for management
        _self.infowindows.push(infoWindow);

    },

    displayMetrics: function(data) {
        var _self = this;
        var groupEl = null;
        _self.metricsElement.empty();

        groupEl = _self.createAccordionGroup('Global');
        groupEl.find('.metric-body').addClass('show');

        _self.addMetricToAccordionGroup(groupEl, 'Current Outages', data.metrics.currentOutages);
        //figure out what this value represents
        //_self.displayMetric('Duration of Outages', data.metrics.durationOutages);

        var customersAffected = 0;
        var crewDispatched = 0;
        var reportedOutages = 0;
        var outagesRepairInProgress = 0;

        _.each(data.dispatches, function(v) {
            customersAffected += v.customerQty;
            crewDispatched += v.crewQty;
            switch (v.jobStatus) {
              case 'OUTAGE_REPORTED':
                reportedOutages++;
                break;
              case 'REPAIR_IN_PROGRESS':
                outagesRepairInProgress++;
                break;
              }
        });

        _self.addMetricToAccordionGroup(groupEl, 'Reported Outages', reportedOutages);
        _self.addMetricToAccordionGroup(groupEl, 'Repair in Progresses', outagesRepairInProgress);
        _self.addMetricToAccordionGroup(groupEl, 'Customers Affected', customersAffected);
        _self.addMetricToAccordionGroup(groupEl, 'Crew Dispatched', crewDispatched);

        _self.addMetricToAccordionGroup(groupEl,
          'Smart Grid Restores (last 24 hours)',
          data.metrics.smartGridRestores, true);
          _self.addMetricToAccordionGroup(groupEl,
            'Manual Restores (last 24 hours)',
            data.metrics.manualRestores, true);
        _self.addMetricToAccordionGroup(groupEl, 'Prevented Outages', data.metrics.preventedOutages, true);
        _self.addMetricToAccordionGroup(groupEl, 'Auto restored Outages', data.metrics.autoRestoredOutages, true);
        _self.addMetricToAccordionGroup(groupEl, 'Prevented Outages', data.metrics.preventedOutages, true);
        _self.addMetricToAccordionGroup(groupEl, 'Total smart grid activity', data.metrics.totalSmartGridActivity, true);

        var districtOutages = _.sortBy(data.districtOutages, 'name');
        _.each(districtOutages, function(v) {
            var disable = true;
            groupEl = _self.createAccordionGroup(v.name);
            if (v.incidents) {
                _self.addMetricToAccordionGroup(groupEl, 'Incidents', v.incidents);
                disable = false;
            }
            if (v.customersAffected) {
                _self.addMetricToAccordionGroup(groupEl, 'Customers Affected', v.customersAffected);
                disable = false;
            }
            if (disable) {
                groupEl.remove();
                //groupEl.find('.metric-title').attr('href', '').addClass('disabled');
            }
        });

    },

    createAccordionGroup: function(title) {
        var _self = this;
        var el = _self.metricsTemplate.clone();
        var id = 't' +(title +'_'+ (Math.floor(Math.random() * 10000))).hashCode();

        el.find('.metric-title').attr('href', '#'+id).text(title);
        el.find('.metric-body').attr('id', id);
        _self.metricsElement.append(el);

        return el;
    },

    addMetricToAccordionGroup: function(groupEl, label, value, displayIfNotNull) {
        var _self = this;
        if (!displayIfNotNull || (displayIfNotNull && !_.isNull(value))) {
          groupEl.find('table > tbody').append('
'+ label +'	'+ value +'
');
        }
    }
};
<commit_msg>Added number formating for numbers in UI<commit_after>function OutageMap(mapElement,metricsElement, zoom, centerLocation) {
    this.mapElement = mapElement;
    this.zoom = zoom;
    this.centerLocation = centerLocation;
    this.centerLocation.lat = parseFloat(this.centerLocation.lat);
    this.centerLocation.lng = parseFloat(this.centerLocation.lng);
    this.map = null;
    this.data = null;
    this.infowindows = [];
    this.metricsElement = metricsElement;
    this.metricsTemplate = metricsElement.find('.metric-template').clone();
    this.overlays = [];
    this.metricsTemplate.removeClass('metric-template hide');
    this.dispatchJobInfo = {
      colors: {
        DEFAULT: '#FF0000',
        OUTAGE_REPORTED: '#FF0000',
        REPAIR_IN_PROGRESS: '#ff8c4f'
      },
      userFriendlyName: {
        OUTAGE_REPORTED: 'Outage Reported',
        REPAIR_IN_PROGRESS: 'Repair in Progress'
      }
    };
}

OutageMap.prototype = {
    init: function() {
        var _self = this;
        _self.initialized = true;
        _self.numberFormater = new Intl.NumberFormat();
    },

    load: function() {
        var _self = this;
        if (!_self.initialized) {
            _self.init();
        }
        _self.map = new google.maps.Map(_self.mapElement[0], {
            zoom: _self.zoom,
            center: _self.centerLocation,
            mapTypeId: 'terrain'
        });

    },

    loadOutageDataFromRemote: function(id) {
        var _self = this;
        var route = null;
        if (_.isUndefined((id))) {
            route = Routing.generate('ajax_fetch_current_outage');
        } else {
            route = Routing.generate('ajax_fetch_outage', {id: id});
        }
        $.post(route).done(function(data) {
            _self.saveOutageData(data.id, data);
            _self.drawData(data);
            _self.mapElement.trigger('outage:loaded', data);
        });
    },

    saveOutageData: function(id, data) {
        sessionStorage.setItem('outage_'+ id, JSON.stringify(data));
    },

    loadOutageData: function(id) {
        var _self = this;
        _self.clearOverlays();

        if (_.isUndefined((id))) {
            _self.loadOutageDataFromRemote();
        } else {
            var data = JSON.parse(sessionStorage.getItem('outage_'+ id));
            if (!data) {
                _self.loadOutageDataFromRemote(id);
            } else {
                _self.drawData(data);
                _self.mapElement.trigger('outage:loaded', data);
            }
        }
    },

    clearOverlays: function() {
        var _self = this;
        _.each(_self.overlays, function(v)  {
            v.setMap(null);
        });
        _self.overlays = [];
    },

    drawData: function(data) {
        var _self = this;
        _self.data = data;
        _.each(data.boundaries, function(v) {
            var districtOutage = _.find(data.districtOutages, function(o) { return v.name === o.name });
            _self.overlays.push(_self.drawBoundary(v, districtOutage, v.latLng, '#3494d3', 0.2, 1));
        });
        _.each(data.dispatches, function(v) {
            var center = {lat: parseFloat(v.latitude), lng: parseFloat(v.longitude)};
            var color = _self.dispatchJobInfo.colors['DEFAULT'];
            if (!_.isUndefined(_self.dispatchJobInfo.colors[v.jobStatus])) {
              color = _self.dispatchJobInfo.colors[v.jobStatus];
            }
            _self.overlays.push(_self.drawDispatchesOutages(v, center, color, 0.5, 1, v.customerQty));
        });

        _self.displayMetrics(data);
    },

    drawBoundary: function(boundary, districtOutage, paths, color, opacity, strokeWeight) {
        var _self = this;
        var polygon = new google.maps.Polygon({
          paths: paths,
          strokeColor: EPBOutage.darkenHexColor(color),
          strokeOpacity: 1,
          strokeWeight: strokeWeight,
          fillColor: color,
          fillOpacity: opacity,
          map: _self.map
        });

        if (!_.isUndefined(districtOutage)) {
            var content = "
"+ boundary.name +"

";
            if (districtOutage.incidents) {
                content += "
Incidents: "+ districtOutage.incidents +"
";
            }
            if (districtOutage.customersAffected) {
                content += "
Customers affected "+ districtOutage.customersAffected +"
";
            }

            var bounds = new google.maps.LatLngBounds();
            _.each(paths, function(v) {
                bounds.extend(v);
            });

            var mapLabel = new MapLabel({
                text: boundary.name,
                position: bounds.getCenter(),
                map: _self.map,
                fontSize: 12,
                align: 'right'
            });

            _self.overlays.push(mapLabel);
        }

        return polygon;
    },

    drawDispatchesOutages: function(dispatch, center, color, opacity, strokeWeight, numberOfOutages) {
        var _self = this;
        if (numberOfOutages < 10) { numberOfOutages = 10; }
        var radius = Math.sqrt(numberOfOutages) * 100;
        var circle = new google.maps.Circle({
            strokeColor: EPBOutage.darkenHexColor(color),
            strokeOpacity: 1,
            strokeWeight: strokeWeight,
            fillColor: color,
            fillOpacity: opacity,
            map: _self.map,
            center: center,
            radius: radius
          });

          var jobStatus = dispatch.jobStatus;
          if (!_.isUndefined(_self.dispatchJobInfo.userFriendlyName[dispatch.jobStatus])) {
            jobStatus = _self.dispatchJobInfo.userFriendlyName[dispatch.jobStatus];
          }
        var content = "
Outage Info

Job Status: "+ jobStatus +"
"+
                "
Crew dispatched: "+ _self.numberFormater.format(dispatch.crewQty) +"
"+
                "
Customers affected "+ _self.numberFormater.format(dispatch.customerQty) +"
";

        _self.addInfowindow(circle, content, circle.getCenter());
        return circle;
    },

    addInfowindow: function(object, content, position) {
        var _self = this;
        var infoWindow = new google.maps.InfoWindow({
            content: content
        });
        var openTimeout = null;
        var closeTimeout = null;

        object.addListener('mouseover', function () {
            if (!_.isNull(openTimeout)) {
                clearTimeout(openTimeout);
            }
            if (!_.isNull(closeTimeout)) {
                clearTimeout(closeTimeout);
            }
            openTimeout = setTimeout(function() {
                _.each(_self.infowindows, function(v) {
                    v.close();
                });
                infoWindow.open(_self.map, object);
                infoWindow.setPosition(position);
            }, 500);

        });

        object.addListener('mouseout', function() {
            if (!_.isNull(closeTimeout)) {
                clearTimeout(closeTimeout);
            }
            closeTimeout = setTimeout(function() {
                infoWindow.close();
            }, 1000);
        });

        //add infowindows to the global space for management
        _self.infowindows.push(infoWindow);

    },

    displayMetrics: function(data) {
        var _self = this;
        var groupEl = null;
        _self.metricsElement.empty();

        groupEl = _self.createAccordionGroup('Global');
        groupEl.find('.metric-body').addClass('show');

        _self.addMetricToAccordionGroup(groupEl, 'Current Outages', _self.numberFormater.format(data.metrics.currentOutages));
        //figure out what this value represents
        //_self.displayMetric('Duration of Outages', data.metrics.durationOutages);

        var customersAffected = 0;
        var crewDispatched = 0;
        var reportedOutages = 0;
        var outagesRepairInProgress = 0;

        _.each(data.dispatches, function(v) {
            customersAffected += v.customerQty;
            crewDispatched += v.crewQty;
            switch (v.jobStatus) {
              case 'OUTAGE_REPORTED':
                reportedOutages++;
                break;
              case 'REPAIR_IN_PROGRESS':
                outagesRepairInProgress++;
                break;
              }
        });

        _self.addMetricToAccordionGroup(groupEl, 'Reported Outages', _self.numberFormater.format(reportedOutages));
        _self.addMetricToAccordionGroup(groupEl, 'Repair in Progresses', _self.numberFormater.format(outagesRepairInProgress));
        _self.addMetricToAccordionGroup(groupEl, 'Customers Affected', _self.numberFormater.format(customersAffected));
        _self.addMetricToAccordionGroup(groupEl, 'Crew Dispatched', _self.numberFormater.format(crewDispatched));

        _self.addMetricToAccordionGroup(groupEl,
          'Smart Grid Restores (last 24 hours)',
            _self.numberFormater.format(data.metrics.smartGridRestores), true);
          _self.addMetricToAccordionGroup(groupEl,
            'Manual Restores (last 24 hours)',
            _self.numberFormater.format(data.metrics.manualRestores), true);
        _self.addMetricToAccordionGroup(groupEl, 'Prevented Outages', _self.numberFormater.format(data.metrics.preventedOutages), true);
        _self.addMetricToAccordionGroup(groupEl, 'Auto restored Outages', _self.numberFormater.format(data.metrics.autoRestoredOutages), true);
        _self.addMetricToAccordionGroup(groupEl, 'Prevented Outages', _self.numberFormater.format(data.metrics.preventedOutages), true);
        _self.addMetricToAccordionGroup(groupEl, 'Total smart grid activity', _self.numberFormater.format(data.metrics.totalSmartGridActivity), true);

        var districtOutages = _.sortBy(data.districtOutages, 'name');
        _.each(districtOutages, function(v) {
            var disable = true;
            groupEl = _self.createAccordionGroup(v.name);
            if (v.incidents) {
                _self.addMetricToAccordionGroup(groupEl, 'Incidents', _self.numberFormater.format(v.incidents));
                disable = false;
            }
            if (v.customersAffected) {
                _self.addMetricToAccordionGroup(groupEl, 'Customers Affected', _self.numberFormater.format(v.customersAffected));
                disable = false;
            }
            if (disable) {
                groupEl.remove();
                //groupEl.find('.metric-title').attr('href', '').addClass('disabled');
            }
        });

    },

    createAccordionGroup: function(title) {
        var _self = this;
        var el = _self.metricsTemplate.clone();
        var id = 't' +(title +'_'+ (Math.floor(Math.random() * 10000))).hashCode();

        el.find('.metric-title').attr('href', '#'+id).text(title);
        el.find('.metric-body').attr('id', id);
        _self.metricsElement.append(el);

        return el;
    },

    addMetricToAccordionGroup: function(groupEl, label, value, displayIfNotNull) {
        var _self = this;
        if (!displayIfNotNull || (displayIfNotNull && !_.isNull(value))) {
          groupEl.find('table > tbody').append('
'+ label +'	'+ value +'
');
        }
    }
};
<|endoftext|>


<commit_before>/*jshint node:true*/
module.exports = {
  description: 'Adds necessary packages to application',

  // locals: function(options) {
  //   // Return custom template variables here.
  //   return {
  //     foo: options.entity.options.foo
  //   };
  // }

  afterInstall: function(options) {
    var _this = this;
    return this.addBowerPackagesToProject([
      { name: 'localforage', target: '1.3.3' }
    ]).then(function() {
      return _this.addAddonsToProject({
        packages: [
          'https://github.com/Flexberry/ember-localforage-adapter.git',
          { name: 'ember-browserify', target: '1.1.9' }
        ]
      });
    }).then(function () {
      return _this.addPackagesToProject([
        { name: 'dexie', target: '1.3.6' }
      ]);
    });
  },

  normalizeEntityName: function() {}
};
<commit_msg>Fix `globals` label for jshint<commit_after>/* globals module */
module.exports = {
  description: 'Adds necessary packages to application',

  // locals: function(options) {
  //   // Return custom template variables here.
  //   return {
  //     foo: options.entity.options.foo
  //   };
  // }

  afterInstall: function(options) {
    var _this = this;
    return this.addBowerPackagesToProject([
      { name: 'localforage', target: '1.3.3' }
    ]).then(function() {
      return _this.addAddonsToProject({
        packages: [
          'https://github.com/Flexberry/ember-localforage-adapter.git',
          { name: 'ember-browserify', target: '1.1.9' }
        ]
      });
    }).then(function () {
      return _this.addPackagesToProject([
        { name: 'dexie', target: '1.3.6' }
      ]);
    });
  },

  normalizeEntityName: function() {}
};
<|endoftext|>


<commit_before>var Hapi = require('hapi');
var path = require('path');

var server = Hapi.createServer('localhost', Number(process.argv[2] || 8080));
server.route({
    method: 'GET',
    path: '/',
    handler: {
        file: path.join(__dirname + '/index.html')
    }
});
server.start()
<commit_msg>Minor fixes to solution.<commit_after>var Hapi = require('hapi');
var path = require('path');

var server = Hapi.createServer('localhost', Number(process.argv[2] || 8080));
server.route({
    method: 'GET',
    path: '/',
    handler: {
        file: path.join(__dirname, '/index.html')
    }
});
server.start();
<|endoftext|>


<commit_before><commit_msg>removed dropdown<commit_after><|endoftext|>


<commit_before>(function() {
  'use strict';

  function listenToClick(element, name, fn) {
    if (document.addEventListener) {
      element.addEventListener(name, fn, false);
    } else {
      element.attachEvent((name === 'click') ? 'onclick' : name, fn);
    }
  }

  function handleClicks(elem, fn) {
    if (document.addEventListener) {
      // For all major browsers, except IE 8 and earlier
      elem.addEventListener("click", fn, false);
      elem.addEventListener("touchstart", fn, false);
    } else if (document.attachEvent) {
      // For IE 8 and earlier versions
      elem.attachEvent("onclick", fn, false);
      elem.attachEvent("touchstart", fn, false);
    }
  };

  function hasClass(el, className) {
    if (el.classList)
      return el.classList.contains(className)
    else
      return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
  }

  function my_addClass(el, className) {
    if (el.classList)
      el.classList.add(className)
    else if (!hasClass(el, className)) el.className += " " + className
  }

  function my_removeClass(el, className) {
    if (el.classList)
      el.classList.remove(className)
    else if (hasClass(el, className)) {
      var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
      el.className=el.className.replace(reg, ' ')
    }
  }

  function scrollTop(element, to, duration) {
    var start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    var animateScroll = function(){
      currentTime += increment;
      var val = Math.easeInOutQuad(currentTime, start, change, duration);
      element.scrollTop = val;
      if(currentTime < duration) {
        setTimeout(animateScroll, increment);
      }
    };
    animateScroll();
  }

  //t = current time
  //b = start value
  //c = change in value
  //d = duration
  Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
  }

  function each(o, cb, s){
    var n;
    if (!o){
      return 0;
    }
    s = !s ? o : s;
    if (o instanceof Array){
      // Indexed arrays, needed for Safari
      for (n=0; n<o.length; n++) {
        if (cb.call(s, o[n], n, o) === false){
          return 0;
        }
      }
    } else {
      // Hashtables
      for (n in o){
        if (o.hasOwnProperty(n)) {
          if (cb.call(s, o[n], n, o) === false){
            return 0;
          }
        }
      }
    }
    return 1;
  }

  domready(function() {

    var scrollElements = document.querySelectorAll('[data-scroll-element]');

    var inValidRange = function(offset, limit) {
      return offset >= 0 && offset < limit;
    };

    var setVisibility = function(element, nextOffset, limit) {
      if(inValidRange(nextOffset, limit)) {
        my_removeClass(element, 'disabled');
      } else {
        my_addClass(element, 'disabled');
      }
    };

    var setVisibilityAll = function(elements, newOffset) {
      var
        scrollElement,
        increment,
        nextOffset,
        limit;

      each(elements, function(el) {
        scrollElement = document.querySelector(el.dataset.scrollElement);
        increment  = parseInt(el.dataset.scrollIncrement);
        nextOffset = newOffset + increment;
        limit      = parseInt(scrollElement.dataset.scrollLimit);

        setVisibility(el, nextOffset, limit);
      });
    };

    var resetScroll = function(element) {
      element.scrollTop = 0;
      element.dataset.scrollOffset = 0;
    };

    each(document.querySelectorAll('[data-clipboard-target]'), function(el) {
      var clipboard = new Clipboard(el);
      var notification;

      var notify = function(clipboardNotification, notificationText) {
        notification = document.getElementById(clipboardNotification.slice(1));
        notification.textContent = notificationText;
        my_addClass(notification, 'in');
        setTimeout(function() {
          my_removeClass(notification, 'in');
        }, 1400);
      };

      var notifySuccess = function(e) {
        notify(e.trigger.dataset.clipboardNotification, "Copied!");
      };

      var notifyFailure = function(e) {
        //if the copy function failed the text should still be selected, so just ask the user to hit ctrl+c
        notify(e.trigger.dataset.clipboardNotification, "Press Ctrl+C to copy");
      };

      clipboard.on('success', notifySuccess);
      clipboard.on('error', notifyFailure);
      handleClicks(el, function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('copy_btn_clicked', e.type);
        }
      });
    });

    each(scrollElements, function(el) {
      var element = document.querySelector(el.dataset.scrollElement);
      var increment = parseInt(el.dataset.scrollIncrement);
      var limit     = parseInt(element.dataset.scrollLimit.valueOf());
      var offset    = parseInt(element.dataset.scrollOffset.valueOf());
      var newOffset;

      element.dataset.scrollLimit = limit;

      var nextOffset = offset + increment;

      setVisibility(el, nextOffset, limit);

      // Force IE to forget previous scroll top value
      resetScroll(element);

      listenToClick(el, 'click', function() {
        offset = parseInt(element.dataset.scrollOffset);

        newOffset = offset + increment;

        if (inValidRange(newOffset, limit)) {
          scrollTop(element, document.getElementById(newOffset).offsetTop, 400);
          element.dataset.scrollOffset = newOffset;

          setVisibilityAll(scrollElements, newOffset);
        }
      });
    });

    each(document.querySelectorAll('[data-moment]'), function(el) {
      var time = moment(parseInt(el.textContent));
      el.textContent = time.fromNow();
    });

    each(document.getElementsByClassName('squatch-header-close'), function(el) {
      handleClicks(el, function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('close_popup', e.type);
        }
      });
    });

    // CTA
    each(document.getElementsByClassName('cta-container'), function(el) {
      el.onclick = function() {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('open_popup', e.type);
        }
      }
    });

    // Popup stuff
    each(document.querySelectorAll('[data-open-panel]'), function(el) {
      var element = document.getElementById(el.dataset.openPanel.slice(1));

      el.onclick = function() {
        my_addClass(element, 'open');
      };
    });

    each(document.querySelectorAll('[data-close-panel]'), function(el) {
      var element = document.getElementById(el.dataset.closePanel.slice(1));

      el.onclick = function() {
        my_removeClass(element, 'open');
      }
    });

    var setContainerHeight = function(containerEl) {
      var bodyEl           = document.getElementsByClassName('squatch-body')[0];
      var titleEl          = document.getElementsByClassName('squatch-title')[0];
      var titleStyle       = getComputedStyle(titleEl);
      var panelEl          = document.getElementById('squatch-panel');
      var referralsEl      = document.getElementsByClassName('squatch-referrals')[0];
      var referralsTitleEl = document.getElementsByClassName('squatch-referrals-title')[0];

      var bodyHeight = bodyEl.offsetHeight;
      var bodyHeightWithoutTitle = bodyHeight - titleEl.offsetHeight - parseInt(titleStyle.marginTop) - parseInt(titleStyle.marginBottom) - titleEl.offsetTop;
      var panelHeight = panelEl ? panelEl.offsetHeight : 0;

      if (referralsEl.style.display !== 'none') {
        panelHeight -= referralsEl.offsetHeight;
      }

      if (referralsTitleEl.style.display !== 'none') {
        panelHeight -= referralsTitleEl.offsetHeight;
      }

      containerEl.style.height = bodyHeight + panelHeight + "px";

      var stylesheet = document.createElement('style');
      stylesheet.type = 'text/css';

      var css = '#squatch-panel.open {' +
        '-webkit-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-ms-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-o-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        'transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '}' +
        'html.lt-ie9 #squatch-panel.open {' +
        'top: -' + bodyHeightWithoutTitle + 'px;' +
        '}';

      if (stylesheet.styleSheet){
        // IE
        stylesheet.styleSheet.cssText = css;
      } else {
        // W3C Standard
        stylesheet.appendChild(document.createTextNode(css));
      }

      document.querySelector('head').appendChild(stylesheet);
    };

    var containerEl = document.getElementsByClassName('squatch-container-popup')[0];
    console.log(containerEl);

    if (containerEl) {
     window.onload = function() {
       setContainerHeight(containerEl);
     }

    }
  });

})();
<commit_msg>update cta<commit_after>(function() {
  'use strict';

  function listenToClick(element, name, fn) {
    if (document.addEventListener) {
      element.addEventListener(name, fn, false);
    } else {
      element.attachEvent((name === 'click') ? 'onclick' : name, fn);
    }
  }

  function handleClicks(elem, fn) {
    if (document.addEventListener) {
      // For all major browsers, except IE 8 and earlier
      elem.addEventListener("click", fn, false);
      elem.addEventListener("touchstart", fn, false);
    } else if (document.attachEvent) {
      // For IE 8 and earlier versions
      elem.attachEvent("onclick", fn, false);
      elem.attachEvent("touchstart", fn, false);
    }
  };

  function hasClass(el, className) {
    if (el.classList)
      return el.classList.contains(className)
    else
      return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
  }

  function my_addClass(el, className) {
    if (el.classList)
      el.classList.add(className)
    else if (!hasClass(el, className)) el.className += " " + className
  }

  function my_removeClass(el, className) {
    if (el.classList)
      el.classList.remove(className)
    else if (hasClass(el, className)) {
      var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
      el.className=el.className.replace(reg, ' ')
    }
  }

  function scrollTop(element, to, duration) {
    var start = element.scrollTop,
        change = to - start,
        currentTime = 0,
        increment = 20;

    var animateScroll = function(){
      currentTime += increment;
      var val = Math.easeInOutQuad(currentTime, start, change, duration);
      element.scrollTop = val;
      if(currentTime < duration) {
        setTimeout(animateScroll, increment);
      }
    };
    animateScroll();
  }

  //t = current time
  //b = start value
  //c = change in value
  //d = duration
  Math.easeInOutQuad = function (t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
  }

  function each(o, cb, s){
    var n;
    if (!o){
      return 0;
    }
    s = !s ? o : s;
    if (o instanceof Array){
      // Indexed arrays, needed for Safari
      for (n=0; n<o.length; n++) {
        if (cb.call(s, o[n], n, o) === false){
          return 0;
        }
      }
    } else {
      // Hashtables
      for (n in o){
        if (o.hasOwnProperty(n)) {
          if (cb.call(s, o[n], n, o) === false){
            return 0;
          }
        }
      }
    }
    return 1;
  }

  domready(function() {

    var scrollElements = document.querySelectorAll('[data-scroll-element]');

    var inValidRange = function(offset, limit) {
      return offset >= 0 && offset < limit;
    };

    var setVisibility = function(element, nextOffset, limit) {
      if(inValidRange(nextOffset, limit)) {
        my_removeClass(element, 'disabled');
      } else {
        my_addClass(element, 'disabled');
      }
    };

    var setVisibilityAll = function(elements, newOffset) {
      var
        scrollElement,
        increment,
        nextOffset,
        limit;

      each(elements, function(el) {
        scrollElement = document.querySelector(el.dataset.scrollElement);
        increment  = parseInt(el.dataset.scrollIncrement);
        nextOffset = newOffset + increment;
        limit      = parseInt(scrollElement.dataset.scrollLimit);

        setVisibility(el, nextOffset, limit);
      });
    };

    var resetScroll = function(element) {
      element.scrollTop = 0;
      element.dataset.scrollOffset = 0;
    };

    each(document.querySelectorAll('[data-clipboard-target]'), function(el) {
      var clipboard = new Clipboard(el);
      var notification;

      var notify = function(clipboardNotification, notificationText) {
        notification = document.getElementById(clipboardNotification.slice(1));
        notification.textContent = notificationText;
        my_addClass(notification, 'in');
        setTimeout(function() {
          my_removeClass(notification, 'in');
        }, 1400);
      };

      var notifySuccess = function(e) {
        notify(e.trigger.dataset.clipboardNotification, "Copied!");
      };

      var notifyFailure = function(e) {
        //if the copy function failed the text should still be selected, so just ask the user to hit ctrl+c
        notify(e.trigger.dataset.clipboardNotification, "Press Ctrl+C to copy");
      };

      clipboard.on('success', notifySuccess);
      clipboard.on('error', notifyFailure);
      handleClicks(el, function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('copy_btn_clicked', e.type);
        }
      });
    });

    each(scrollElements, function(el) {
      var element = document.querySelector(el.dataset.scrollElement);
      var increment = parseInt(el.dataset.scrollIncrement);
      var limit     = parseInt(element.dataset.scrollLimit.valueOf());
      var offset    = parseInt(element.dataset.scrollOffset.valueOf());
      var newOffset;

      element.dataset.scrollLimit = limit;

      var nextOffset = offset + increment;

      setVisibility(el, nextOffset, limit);

      // Force IE to forget previous scroll top value
      resetScroll(element);

      listenToClick(el, 'click', function() {
        offset = parseInt(element.dataset.scrollOffset);

        newOffset = offset + increment;

        if (inValidRange(newOffset, limit)) {
          scrollTop(element, document.getElementById(newOffset).offsetTop, 400);
          element.dataset.scrollOffset = newOffset;

          setVisibilityAll(scrollElements, newOffset);
        }
      });
    });

    each(document.querySelectorAll('[data-moment]'), function(el) {
      var time = moment(parseInt(el.textContent));
      el.textContent = time.fromNow();
    });

    each(document.getElementsByClassName('squatch-header-close'), function(el) {
      handleClicks(el, function(e) {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('close_popup', e.type);
        }
      });
    });

    // CTA
    each(document.getElementsByClassName('cta-container'), function(el) {
      el.onclick = function() {
        if (window.parent.squatch.eventBus) {
          window.parent.squatch.eventBus.dispatch('open_popup', e.type);
        }
      }
    });

    // Popup stuff
    each(document.querySelectorAll('[data-open-panel]'), function(el) {
      var element = document.getElementById(el.dataset.openPanel.slice(1));

      el.onclick = function() {
        my_addClass(element, 'open');
      };
    });

    each(document.querySelectorAll('[data-close-panel]'), function(el) {
      var element = document.getElementById(el.dataset.closePanel.slice(1));

      el.onclick = function() {
        my_removeClass(element, 'open');
      }
    });

    var setContainerHeight = function(containerEl) {
      console.log(containerEl);

      var bodyEl           = document.getElementsByClassName('squatch-body')[0];
      var titleEl          = document.getElementsByClassName('squatch-title')[0];
      var titleStyle       = getComputedStyle(titleEl);
      var panelEl          = document.getElementById('squatch-panel');
      var referralsEl      = document.getElementsByClassName('squatch-referrals')[0];
      var referralsTitleEl = document.getElementsByClassName('squatch-referrals-title')[0];

      var bodyHeight = bodyEl.offsetHeight;
      var bodyHeightWithoutTitle = bodyHeight - titleEl.offsetHeight - parseInt(titleStyle.marginTop) - parseInt(titleStyle.marginBottom) - titleEl.offsetTop;
      var panelHeight = panelEl ? panelEl.offsetHeight : 0;

      if (referralsEl && referralsEl.style.display !== 'none') {
        panelHeight -= referralsEl.offsetHeight;
      }

      if (referralsTitleEl.style.display !== 'none') {
        panelHeight -= referralsTitleEl.offsetHeight;
      }

      containerEl.style.height = bodyHeight + panelHeight + "px";

      var stylesheet = document.createElement('style');
      stylesheet.type = 'text/css';

      var css = '#squatch-panel.open {' +
        '-webkit-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-ms-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '-o-transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        'transform: translate(0, -' + bodyHeightWithoutTitle + 'px);' +
        '}' +
        'html.lt-ie9 #squatch-panel.open {' +
        'top: -' + bodyHeightWithoutTitle + 'px;' +
        '}';

      if (stylesheet.styleSheet){
        // IE
        stylesheet.styleSheet.cssText = css;
      } else {
        // W3C Standard
        stylesheet.appendChild(document.createTextNode(css));
      }

      document.querySelector('head').appendChild(stylesheet);
    };

    var containerEl = document.getElementsByClassName('squatch-container-popup')[0];

    if (containerEl) {
     window.onload = function() {
       setContainerHeight(containerEl);
     }

    }
  });

})();
<|endoftext|>


<commit_before>/*  Function to check API key */

var checkApiKey = function(input, callback) {
    var apiKey = input;
    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader('X-AUTH', apiKey);
        }
    });

    // Send request to check API key and also store the Xuid on success
    $.get('https://xboxapi.com/v2/accountXuid', function (data) {
        log.debug('[DEBUG] Authentication with API key "' + apiKey + '" successful');
        callback(data);
    // Return false
    }).fail(function() {
        log.error('[ERROR] Couldn\'t authenticate. API key invalid or API down?');
        callback(false);
    });
};

/* Retrieve direct API data function */

var retrieveApiData = function(apiKey, endpoint, callback) {
    // Prepare ajax request
    $.ajaxSetup({
        beforeSend: function(xhr) {
            // Add X-AUTH header
            xhr.setRequestHeader('X-AUTH', apiKey);
        }
    });

    log.info('[INFO] API call "GET ' + endpoint + '" started');

    // Fire GET
    $.get('https://xboxapi.com/v2'+endpoint, function (data) {
        log.info('[INFO] API call "GET ' + endpoint + '" finished');
        callback(data);
    // In case of any error, return false
    }).fail(function() {
        log.error('[ERROR] Couldn\'t finish API call "GET ' + endpoint + '". API down?');
        callback(false);
    });
};

/* Retrieve DB data function */

var retrieveDbData = function (endpoint, callback) {
    // PouchDB init
    var pouchdb = new PouchDB(endpoint);
    // Try to get()
    pouchdb.get('jsonData', function(err, doc) {
        // In case of error, return false
        if (err) {
            if (err.status != 404) {
                log.error('[ERROR] Error while retrieving from DB: ', err);
            }
            callback(false);
        }
        // If no error, send data to callback
        if (doc) {
            callback(doc);
        }
    });
};

/* Sumbit API data function */

var submitApiData = function (apikey, endpoint, content, callback) {
    log.info('[INFO] API call "POST ' + endpoint + '" started');

    // Prepare ajax request
    $.ajaxSetup({
        beforeSend: function(xhr) {
            // Add X-AUTH header
            xhr.setRequestHeader('X-AUTH', apikey);
            // Add Content-Type header
            xhr.setRequestHeader('Content-Type', 'application/json');
        }
    });

    // Fire POST
    $.post('https://xboxapi.com/v2'+endpoint, JSON.stringify(content), function (data) {
        log.info('[INFO] API call "POST ' + endpoint + '" successfully finished');
        callback(data);
    // In case of any error, return false
    }).fail(function() {
        log.error('[ERROR] Couldn\'t finish API call "POST ' + endpoint + '"');
        callback(false);
    });
};

/* Submit DB data function */

var submitDbData = function (input, endpoint, callback) {
    // PouchDB init
    var pouchdb = new PouchDB(endpoint);

    // Check for existing data
    pouchdb.get('jsonData', function(err, otherDoc) {
        // If no exisiting data, put() without revision
        // Otherwise put() with revision of outdated data
        if (!otherDoc) {
            // Try to put() the input object into PouchDB
            pouchdb.put(input, 'jsonData', function(err, response) {
                // In case of errors, return false
                if (err) {
                    log.error('[ERROR] Couldn\'t transfer "' + endpoint + '" into database', err);
                    callback(false);
                }
                // If no errors, send response to callback
                if (response){
                    log.info('[INFO] API call "' + endpoint + '" finished');
                    callback(response);
                }
            });
        } else {
            // Try to put() the input object into PouchDB
            pouchdb.put(input, 'jsonData', otherDoc._rev, function(err, response) {
                // In case of errors, return false
                if (err) {
                    log.error("[ERROR] Couldn't transfer settings into database", err);
                    callback(false);
                }
                // If no errors, send response to callback
                if (response){
                    log.info('[INFO] "' + endpoint + '" successfully stored in PouchDB');
                    callback(response);
                }
            });
        }
    });
};

/* Function to send message */

var sendMessage = function(apikey, recipients, message, callback){
    var jsonObject = {};

    jsonObject.to = recipients;
    jsonObject.message = message;

    submitApiData(apikey, '/messages', jsonObject, function(data){
        if (!data) {
            log.error("[ERROR] Couldn't send message - ", recipients, message);
            callback(false);
        } else {
            log.info("[INFO] Message successfully sent!", recipients, message);
            callback(true);
        }
    });
};

/* API call function */

var apiCall = function (apiKey, endpoint, cache, callback) {
    // Show loading spinner
    showLoadingSpinner();

    // Try to get the cached API results out of PouchDB
    retrieveDbData(endpoint, function(data){
        timestampNow = $.now();
        var dataExpiredCondition = (timestampNow - data.timestamp) / 1000,
            dataExpired = (dataExpiredCondition >= cache);

        log.debug('[DEBUG] Check if cache is expired for endpoint "' + endpoint + '"');

        // If no result or caching value exceeded => call API directly
        // Otherwise return cached API results out of PouchDB
        if (!data || dataExpired) {
            // Display caching status of cachable objects in PouchDB
            if (data && dataExpired) {
                log.info('[INFO] Cache expired for "' + endpoint + ': ' + dataExpiredCondition + ' ms > ' + cache);
            }

            // Execute retrieve function
            retrieveApiData(apiKey, endpoint, function(data) {
                // In case of server side API error, return false
                // Otherwise proceed to transfer the API results into local database
                if (!data) {
                    // Hide loading spinner again
                    hideLoadingSpinner();
                    callback(false);
                } else {
                    // Create new object to append a timestamp
                    var jsonObject = {};
                    jsonObject.timestamp  = timestampNow;
                    jsonObject.jsonData = data;

                    // Try to submit the data into the DB
                    submitDbData(jsonObject, endpoint, function(submitData){
                        // Return false in case of error
                        // Otherwise, send to callback
                        if (!submitData) {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(false);
                        } else {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(data);
                        }
                    });
                }
            });
        } else {
            log.debug('[DEBUG] Cache not expired for "' + endpoint + '". Deliver cached version from PouchDB.');
            log.info('[INFO] DB call "' + endpoint + '" started');
            // Retrieve cached data
            retrieveDbData(endpoint, function(data){
                log.info('[INFO] DB call "' + endpoint + '" finished');
                // Hide loading spinner again
                hideLoadingSpinner();
                // Send callback
                callback(data.jsonData);
            });
        }
    });
};

/* API POST call function */

var apiPostCall = function (apiKey, endpoint, postdata, cache, callback) {
    // Show loading spinner
    showLoadingSpinner();

    // Try to get the cached API results out of PouchDB
    retrieveDbData(endpoint, function(data){
        timestampNow = $.now();
        var dataExpiredCondition = (timestampNow - data.timestamp) / 1000,
            dataExpired = (dataExpiredCondition >= cache);

        log.debug('[DEBUG] Check if cache is expired for endpoint "' + endpoint + '"');

        // If no result or caching value exceeded => call API directly
        // Otherwise return cached API results out of PouchDB
        if (!data || dataExpired) {
            // Display caching status of cachable objects in PouchDB
            if (data && dataExpired) {
                log.info('[INFO] Cache expired for "' + endpoint + ': ' + dataExpiredCondition + ' ms > ' + cache);
            }

            // Execute submit function
            submitApiData(apiKey, endpoint, postdata, function(data) {
                // In case of server side API error, return false
                // Otherwise proceed to transfer the API results into local database
                if (!data) {
                    // Hide loading spinner again
                    hideLoadingSpinner();
                    callback(false);
                } else {
                    // Create new object to append a timestamp
                    var jsonObject = {};
                    jsonObject.timestamp  = timestampNow;
                    jsonObject.jsonData = data;

                    // Try to submit the data into the DB
                    submitDbData(jsonObject, endpoint, function(submitData){
                        // Return false in case of error
                        // Otherwise, send to callback
                        if (!submitData) {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(false);
                        } else {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(data);
                        }
                    });
                }
            });
        } else {
            log.debug('[DEBUG] Cache not expired for "' + endpoint + '". Deliver cached version from PouchDB.');
            log.info('[INFO] DB call "' + endpoint + '" started');
            // Retrieve cached data
            retrieveDbData(endpoint, function(data){
                log.info('[INFO] DB call "' + endpoint + '" finished');
                // Hide loading spinner again
                hideLoadingSpinner();
                // Send callback
                callback(data.jsonData);
            });
        }
    });
};

/* Get connectivity status */

function updateConnectivityIndicator(apiKey, presenceObject, cache){
    // Call presence endpoint to render connectivity status of friends
    apiPostCall(apiKey, '/presence', presenceObject, cache, function(data){
        $(data).each(function(k,v){
            $('.bubble[data-xuid="' + v.xuid + '"]').removeClass().addClass('bubble bubble--' + v.state.toLowerCase());
        });
    });
}<commit_msg>Don't show loading cursor in /presence call<commit_after>/*  Function to check API key */

var checkApiKey = function(input, callback) {
    var apiKey = input;
    $.ajaxSetup({
        beforeSend: function(xhr) {
            xhr.setRequestHeader('X-AUTH', apiKey);
        }
    });

    // Send request to check API key and also store the Xuid on success
    $.get('https://xboxapi.com/v2/accountXuid', function (data) {
        log.debug('[DEBUG] Authentication with API key "' + apiKey + '" successful');
        callback(data);
    // Return false
    }).fail(function() {
        log.error('[ERROR] Couldn\'t authenticate. API key invalid or API down?');
        callback(false);
    });
};

/* Retrieve direct API data function */

var retrieveApiData = function(apiKey, endpoint, callback) {
    // Prepare ajax request
    $.ajaxSetup({
        beforeSend: function(xhr) {
            // Add X-AUTH header
            xhr.setRequestHeader('X-AUTH', apiKey);
        }
    });

    log.info('[INFO] API call "GET ' + endpoint + '" started');

    // Fire GET
    $.get('https://xboxapi.com/v2'+endpoint, function (data) {
        log.info('[INFO] API call "GET ' + endpoint + '" finished');
        callback(data);
    // In case of any error, return false
    }).fail(function() {
        log.error('[ERROR] Couldn\'t finish API call "GET ' + endpoint + '". API down?');
        callback(false);
    });
};

/* Retrieve DB data function */

var retrieveDbData = function (endpoint, callback) {
    // PouchDB init
    var pouchdb = new PouchDB(endpoint);
    // Try to get()
    pouchdb.get('jsonData', function(err, doc) {
        // In case of error, return false
        if (err) {
            if (err.status != 404) {
                log.error('[ERROR] Error while retrieving from DB: ', err);
            }
            callback(false);
        }
        // If no error, send data to callback
        if (doc) {
            callback(doc);
        }
    });
};

/* Sumbit API data function */

var submitApiData = function (apikey, endpoint, content, callback) {
    log.info('[INFO] API call "POST ' + endpoint + '" started');

    // Prepare ajax request
    $.ajaxSetup({
        beforeSend: function(xhr) {
            // Add X-AUTH header
            xhr.setRequestHeader('X-AUTH', apikey);
            // Add Content-Type header
            xhr.setRequestHeader('Content-Type', 'application/json');
        }
    });

    // Fire POST
    $.post('https://xboxapi.com/v2'+endpoint, JSON.stringify(content), function (data) {
        log.info('[INFO] API call "POST ' + endpoint + '" successfully finished');
        callback(data);
    // In case of any error, return false
    }).fail(function() {
        log.error('[ERROR] Couldn\'t finish API call "POST ' + endpoint + '"');
        callback(false);
    });
};

/* Submit DB data function */

var submitDbData = function (input, endpoint, callback) {
    // PouchDB init
    var pouchdb = new PouchDB(endpoint);

    // Check for existing data
    pouchdb.get('jsonData', function(err, otherDoc) {
        // If no exisiting data, put() without revision
        // Otherwise put() with revision of outdated data
        if (!otherDoc) {
            // Try to put() the input object into PouchDB
            pouchdb.put(input, 'jsonData', function(err, response) {
                // In case of errors, return false
                if (err) {
                    log.error('[ERROR] Couldn\'t transfer "' + endpoint + '" into database', err);
                    callback(false);
                }
                // If no errors, send response to callback
                if (response){
                    log.info('[INFO] API call "' + endpoint + '" finished');
                    callback(response);
                }
            });
        } else {
            // Try to put() the input object into PouchDB
            pouchdb.put(input, 'jsonData', otherDoc._rev, function(err, response) {
                // In case of errors, return false
                if (err) {
                    log.error("[ERROR] Couldn't transfer settings into database", err);
                    callback(false);
                }
                // If no errors, send response to callback
                if (response){
                    log.info('[INFO] "' + endpoint + '" successfully stored in PouchDB');
                    callback(response);
                }
            });
        }
    });
};

/* Function to send message */

var sendMessage = function(apikey, recipients, message, callback){
    var jsonObject = {};

    jsonObject.to = recipients;
    jsonObject.message = message;

    submitApiData(apikey, '/messages', jsonObject, function(data){
        if (!data) {
            log.error("[ERROR] Couldn't send message - ", recipients, message);
            callback(false);
        } else {
            log.info("[INFO] Message successfully sent!", recipients, message);
            callback(true);
        }
    });
};

/* API call function */

var apiCall = function (apiKey, endpoint, cache, callback) {
    // Show loading spinner
    showLoadingSpinner();

    // Try to get the cached API results out of PouchDB
    retrieveDbData(endpoint, function(data){
        timestampNow = $.now();
        var dataExpiredCondition = (timestampNow - data.timestamp) / 1000,
            dataExpired = (dataExpiredCondition >= cache);

        log.debug('[DEBUG] Check if cache is expired for endpoint "' + endpoint + '"');

        // If no result or caching value exceeded => call API directly
        // Otherwise return cached API results out of PouchDB
        if (!data || dataExpired) {
            // Display caching status of cachable objects in PouchDB
            if (data && dataExpired) {
                log.info('[INFO] Cache expired for "' + endpoint + ': ' + dataExpiredCondition + ' ms > ' + cache);
            }

            // Execute retrieve function
            retrieveApiData(apiKey, endpoint, function(data) {
                // In case of server side API error, return false
                // Otherwise proceed to transfer the API results into local database
                if (!data) {
                    // Hide loading spinner again
                    hideLoadingSpinner();
                    callback(false);
                } else {
                    // Create new object to append a timestamp
                    var jsonObject = {};
                    jsonObject.timestamp  = timestampNow;
                    jsonObject.jsonData = data;

                    // Try to submit the data into the DB
                    submitDbData(jsonObject, endpoint, function(submitData){
                        // Return false in case of error
                        // Otherwise, send to callback
                        if (!submitData) {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(false);
                        } else {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(data);
                        }
                    });
                }
            });
        } else {
            log.debug('[DEBUG] Cache not expired for "' + endpoint + '". Deliver cached version from PouchDB.');
            log.info('[INFO] DB call "' + endpoint + '" started');
            // Retrieve cached data
            retrieveDbData(endpoint, function(data){
                log.info('[INFO] DB call "' + endpoint + '" finished');
                // Hide loading spinner again
                hideLoadingSpinner();
                // Send callback
                callback(data.jsonData);
            });
        }
    });
};

/* API POST call function */

var apiPostCall = function (apiKey, endpoint, postdata, cache, callback) {
    // Show loading spinner
    if(endpoint != 'presence') { showLoadingSpinner(); }

    // Try to get the cached API results out of PouchDB
    retrieveDbData(endpoint, function(data){
        timestampNow = $.now();
        var dataExpiredCondition = (timestampNow - data.timestamp) / 1000,
            dataExpired = (dataExpiredCondition >= cache);

        log.debug('[DEBUG] Check if cache is expired for endpoint "' + endpoint + '"');

        // If no result or caching value exceeded => call API directly
        // Otherwise return cached API results out of PouchDB
        if (!data || dataExpired) {
            // Display caching status of cachable objects in PouchDB
            if (data && dataExpired) {
                log.info('[INFO] Cache expired for "' + endpoint + ': ' + dataExpiredCondition + ' ms > ' + cache);
            }

            // Execute submit function
            submitApiData(apiKey, endpoint, postdata, function(data) {
                // In case of server side API error, return false
                // Otherwise proceed to transfer the API results into local database
                if (!data) {
                    // Hide loading spinner again
                    if(endpoint != 'presence') { hideLoadingSpinner(); }
                    callback(false);
                } else {
                    // Create new object to append a timestamp
                    var jsonObject = {};
                    jsonObject.timestamp  = timestampNow;
                    jsonObject.jsonData = data;

                    // Try to submit the data into the DB
                    submitDbData(jsonObject, endpoint, function(submitData){
                        // Return false in case of error
                        // Otherwise, send to callback
                        if (!submitData) {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(false);
                        } else {
                            // Hide loading spinner again
                            hideLoadingSpinner();
                            callback(data);
                        }
                    });
                }
            });
        } else {
            log.debug('[DEBUG] Cache not expired for "' + endpoint + '". Deliver cached version from PouchDB.');
            log.info('[INFO] DB call "' + endpoint + '" started');
            // Retrieve cached data
            retrieveDbData(endpoint, function(data){
                log.info('[INFO] DB call "' + endpoint + '" finished');
                // Hide loading spinner again
                hideLoadingSpinner();
                // Send callback
                callback(data.jsonData);
            });
        }
    });
};

/* Get connectivity status */

function updateConnectivityIndicator(apiKey, presenceObject, cache){
    // Call presence endpoint to render connectivity status of friends
    apiPostCall(apiKey, '/presence', presenceObject, cache, function(data){
        $(data).each(function(k,v){
            $('.bubble[data-xuid="' + v.xuid + '"]').removeClass().addClass('bubble bubble--' + v.state.toLowerCase());
        });
    });
}<|endoftext|>


<commit_before>$( function(){
	$('input[name=prontuario]').mask('AA0000000', {'translation': {
                                        A: {pattern: /[A-Za-z]/}
		}
	});

	$('input[name=nome]').mask('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',{
		'translation' : {
			A: {pattern : /[A-Za-z]/}
		}
	});

	//o do campo senha está na página de cadastro

	$('input[name=rg]').mask('YY.YYY.YYY-Y' , {
		'translation' : {
			Y: {pattern : /[0-9]/}
		}
	});

	// $('input[name=email]').mask("A", {
	// 	'translation': {
	// 		A: { pattern: /[\w@\-.+]/ , recursive : true }
	// 	}
	// });

	$('input[name=cpf]').mask("000.000.000-00");
	$('input[name=data_nasc]').mask("00/00/0000");
	$('input[name=telefone]').mask('(00) 0000-0000');
	$('input[name=celular]').mask('(00) 00000-0000');
	$('input[name=sexo]').mask('AAAAAAAAA' , {
		'translation' : {
			A: {pattern : /[A-Za-z]/}
		}
	});

	$('input[name=patrimonio]').mask('00000000');
	$('input[name=status]').mask('AAAAAAAAAAAAAAA', {
		'translation' : {
			A : {pattern : /[A-Za-z]/}
		}
	});
	$('input[name=descricao]').mask('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', {
		'translation' : {
			A: {pattern : /[A-Za-z]/}
		}
	});

	$('input[name=num_patrimonio]').mask('00000000');

});<commit_msg>Ajustes nas validações<commit_after>$( function(){
	$('input[name=prontuario]').mask('AA0000000', {'translation': {
                                        A: {pattern: /[A-Za-z]/}
		}
	});

	$('input[name=nome]').mask('A',{
		'translation' : {
			A: {pattern : /[A-Za-z]{100}/}
		}
	});

	//o do campo senha está na página de cadastro

	$('input[name=rg]').mask('YY.YYY.YYY-Y' , {
		'translation' : {
			Y: {pattern : /[0-9]/}
		}
	});

	$('input[name=cpf]').mask("000.000.000-00");
	$('input[name=data_nasc]').mask("00/00/0000");
	$('input[name=telefone]').mask('(00) 0000-0000');
	$('input[name=celular]').mask('(00) 00000-0000');
	$('input[name=sexo]').mask('AAAAAAAAA' , {
		'translation' : {
			A: {pattern : /[A-Za-z]/}
		}
	});

	$('input[name=patrimonio]').mask('00000000');
	$('input[name=status]').mask('AAAAAAAAAAAAAAA', {
		'translation' : {
			A : {pattern : /[A-Za-z]/}
		}
	});
	$('input[name=descricao]').mask('A', {
		'translation' : {
			A: {pattern : /[A-Za-z]{100}/}
		}
	});

	$('input[name=num_patrimonio]').mask('00000000');

});<|endoftext|>


<commit_before>jQuery(document).ready(function($) {

    /*
     * jQuery Accessible tab panel system, using ARIA
     * @version v1.4.1
     * Website: http://a11y.nicolas-hoffmann.net/tabs/
     * License MIT: https://github.com/nico3333fr/jquery-accessible-tabs-aria/blob/master/LICENSE
     */
    // Store current URL hash.
    var hash = window.location.hash.replace("#", "");

    /* Tabs ------------------------------------------------------------------------------------------------------------ */
    var $tabs = $(".js-tabs");

    if ($tabs.length) {

        var $tab_list = $tabs.find(".js-tablist");
        $tab_list.each(function() {
            var $this_tab_list = $(this),
                options = $this_tab_list.data(),
                $tabs_prefix_classes = typeof options.tabsPrefixClass !== 'undefined' ? options.tabsPrefixClass + '-' : '',
                $hx = typeof options.hx !== 'undefined' ? options.hx : '',
                $existing_hx = typeof options.existingHx !== 'undefined' ? options.existingHx : '',
                $this_tab_list_items = $this_tab_list.children(".js-tablist__item"),
                $this_tab_list_links = $this_tab_list.find(".js-tablist__link");

            // roles init
            $this_tab_list.attr("role", "tablist"); // ul
            $this_tab_list_items.attr("role", "presentation"); // li
            $this_tab_list_links.attr("role", "tab"); // a

            // classes init
            $this_tab_list.addClass($tabs_prefix_classes + 'tabs__list');
            $this_tab_list_items.addClass($tabs_prefix_classes + 'tabs__item');
            $this_tab_list_links.addClass($tabs_prefix_classes + 'tabs__link');

            // controls/tabindex attributes
            $this_tab_list_links.each(function() {
                var $this = $(this),
                    $hx_generated_class = typeof options.tabsGeneratedHxClass !== 'undefined' ? options.tabsGeneratedHxClass : 'invisible',
                    $href = $this.attr("href"),
                    $controls = $($href),
                    $text = $this.text();

                if ($hx !== "") {
                    $controls.prepend('<' + $hx + ' class="' + $hx_generated_class + '" tabindex="0">' + $text + '</' + $hx + '>');
                }
                if ($existing_hx !== "") {
                    $controls.find($existing_hx + ':first-child').attr('tabindex', 0);
                }
                if (typeof $href !== "undefined" && $href !== "" && $href !== "#") {
                    $this.attr({
                        "aria-controls": $href.replace("#", ""),
                        "tabindex": -1,
                        "aria-selected": "false"
                    });
                }

                $this.removeAttr("href");

            });
        });

        /* Tabs content ---------------------------------------------------------------------------------------------------- */
        $(".js-tabcontent").attr({
                "role": "tabpanel", // contents
                "aria-hidden": "true" // all hidden
                //"tabindex": 0
            })
            .each(function() {
                var $this = $(this),
                    $this_id = $this.attr("id"),
                    $prefix_attribute = $("#label_" + $this_id).closest('.js-tablist').attr('data-tabs-prefix-class'),
                    $tabs_prefix_classes = typeof $prefix_attribute !== 'undefined' ? $prefix_attribute + '-' : '';
                // label by link
                $this.attr("aria-labelledby", "label_" + $this_id);

                $this.addClass($tabs_prefix_classes + 'tabs__content');
            });

        // search if hash is ON not disabled tab
        if (hash !== "" && $("#" + hash + ".js-tabcontent").length !== 0) {
            if ($("#label_" + hash + ".js-tablist__link:not([aria-disabled='true'])").length) {
                // display not disabled
                $("#" + hash + ".js-tabcontent").removeAttr("aria-hidden");
                // selection menu
                $("#label_" + hash + ".js-tablist__link").attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });
            }

        }
        // search if hash is IN not disabled tab
        if (hash !== "" && $("#" + hash).parents('.js-tabcontent').length) {
            var $this_hash = $("#" + hash),
                $tab_content_parent = $this_hash.parents('.js-tabcontent'),
                $tab_content_parent_id = $tab_content_parent.attr('id');

            if ($("#label_" + $tab_content_parent_id + ".js-tablist__link:not([aria-disabled='true'])").length) {
                $tab_content_parent.removeAttr("aria-hidden");
                // selection menu
                $("#label_" + $tab_content_parent_id + ".js-tablist__link").attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });
            }
        }

        // if no selected => select first not disabled
        $tabs.each(function() {
            var $this = $(this),
                $tab_selected = $this.find('.js-tablist__link[aria-selected="true"]'),
                $first_link = $this.find('.js-tablist__link:not([aria-disabled="true"]):first'),
                $first_content = $('#' + $first_link.attr('aria-controls'));

            if ($tab_selected.length === 0) {
                $first_link.attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });
                $first_content.removeAttr("aria-hidden");
            }
        });

        /* Events ---------------------------------------------------------------------------------------------------------- */
        /* click on a tab link */
        $("body").on("click", ".js-tablist__link[aria-disabled='true']", function() {
            return false;
        });
        $("body").on("click", ".js-tablist__link:not([aria-disabled='true'])", function(event) {
                var $this = $(this),
                    $hash_to_update = $this.attr("aria-controls"),
                    $tab_content_linked = $("#" + $this.attr("aria-controls")),
                    $parent = $this.closest(".js-tabs"),
                    $all_tab_links = $parent.find(".js-tablist__link"),
                    $all_tab_contents = $parent.find(".js-tabcontent");

                // aria selected false on all links
                $all_tab_links.attr({
                    "tabindex": -1,
                    "aria-selected": "false"
                });

                // add aria selected on $this
                $this.attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });

                // add aria-hidden on all tabs contents
                $all_tab_contents.attr("aria-hidden", "true");

                // remove aria-hidden on tab linked
                $tab_content_linked.removeAttr("aria-hidden");

                // add fragment (timeout for transitions)
                setTimeout(function() {
                    history.pushState(null, null, location.pathname + location.search + '#' + $hash_to_update)
                }, 1000);

                event.preventDefault();
            })
            /* Key down in tabs */
            .on("keydown", ".js-tablist", function(event) {

                var $parent = $(this).closest('.js-tabs'),
                    $activated = $parent.find('.js-tablist__link[aria-selected="true"]').parent(),
                    $last_link = $parent.find('.js-tablist__item:last-child .js-tablist__link'),
                    $first_link = $parent.find('.js-tablist__item:first-child .js-tablist__link'),
                    $focus_on_tab_only = false,
                    $prev = $activated,
                    $next = $activated;

                // search valid previous
                do {
                    // if we are on first => activate last
                    if ($prev.is(".js-tablist__item:first-child")) {
                        $prev = $last_link.parent();
                    }
                    // else previous
                    else {
                        $prev = $prev.prev();
                    }
                }
                while ($prev.children('.js-tablist__link').attr('aria-disabled') === 'true' && $prev !== $activated);

                // search valid next
                do {
                    // if we are on last => activate first
                    if ($next.is(".js-tablist__item:last-child")) {
                        $next = $first_link.parent();
                    }
                    // else previous
                    else {
                        $next = $next.next();
                    }
                }
                while ($next.children('.js-tablist__link').attr('aria-disabled') === 'true' && $next !== $activated);

                // some event should be activated only if the focus is on tabs (not on tabpanel)
                if ($(document.activeElement).is($parent.find('.js-tablist__link'))) {
                    $focus_on_tab_only = true;
                }

                // catch keyboard event only if focus is on tab
                if ($focus_on_tab_only && !event.ctrlKey) {
                    // strike up or left in the tab
                    if (event.keyCode == 37 || event.keyCode == 38) {

                        $prev.children(".js-tablist__link").click().focus();

                        event.preventDefault();
                    }
                    // strike down or right in the tab
                    else if (event.keyCode == 40 || event.keyCode == 39) {

                        $next.children(".js-tablist__link").click().focus();

                        event.preventDefault();
                    } else if (event.keyCode == 36) {
                        // activate first tab
                        $first_link.click().focus();
                        event.preventDefault();
                    } else if (event.keyCode == 35) {
                        // activate last tab
                        $last_link.click().focus();
                        event.preventDefault();
                    }

                }

            })
            .on("keydown", ".js-tabcontent", function(event) {

                var $this = $(this),
                    $selector_tab_to_focus = $this.attr('aria-labelledby'),
                    $tab_to_focus = $("#" + $selector_tab_to_focus),
                    $parent_item = $tab_to_focus.parent(),
                    $parent_list = $parent_item.parent(),
                    $first_item = $parent_list.find('.js-tablist__item:first-child'),
                    $last_item = $parent_list.find('.js-tablist__item:last-child'),
                    $prev_item = $parent_item,
                    $next_item = $parent_item;

                // CTRL up/Left
                if ((event.keyCode == 37 || event.keyCode == 38) && event.ctrlKey) {
                    $tab_to_focus.focus();
                    event.preventDefault();
                }
                // CTRL PageUp
                if (event.keyCode == 33 && event.ctrlKey) {
                    //$tab_to_focus.focus();

                    // search valid previous
                    do {
                        // if we are on first => last
                        if ($prev_item.is(".js-tablist__item:first-child")) {
                            $prev_item = $last_item;
                        }
                        // else previous
                        else {
                            $prev_item = $prev_item.prev();
                        }
                    }
                    while ($prev_item.children('.js-tablist__link').attr('aria-disabled') === 'true' && $prev_item !== $parent_item);

                    $prev_item.children(".js-tablist__link").click().focus();

                    event.preventDefault();
                }
                // CTRL PageDown
                if (event.keyCode == 34 && event.ctrlKey) {
                    $tab_to_focus.focus();

                    // search valid next
                    do {
                        // if we are on last => first
                        if ($next_item.is(".js-tablist__item:last-child")) {
                            $next_item = $first_item;
                        }
                        // else previous
                        else {
                            $next_item = $next_item.next();
                        }
                    }
                    while ($next_item.children('.js-tablist__link').attr('aria-disabled') === 'true' && $next_item !== $parent_item);

                    $next_item.children(".js-tablist__link").click().focus();

                    event.preventDefault();
                }

            })
            /* click on a tab link */
            .on("click", ".js-link-to-tab", function() {
                var $this = $(this),
                    $tab_to_go = $($this.attr('href')),
                    $button_to_click = $('#' + $tab_to_go.attr('aria-labelledby'));

                if ($button_to_click.attr('aria-disabled') !== 'true') {
                    // activate tabs
                    $button_to_click.click();
                    // give focus to the good button
                    setTimeout(function() {
                        $button_to_click.focus()
                    }, 10);
                }

            });

    }

});
<commit_msg>Linted and re-indented<commit_after>jQuery(document).ready(function($) {

    /*
     * jQuery Accessible tab panel system, using ARIA
     * @version v1.4.1
     * Website: https://a11y.nicolas-hoffmann.net/tabs/
     * License MIT: https://github.com/nico3333fr/jquery-accessible-tabs-aria/blob/master/LICENSE
     */
    // Store current URL hash.
    var hash = window.location.hash.replace("#", "");

    /* Tabs ------------------------------------------------------------------------------------------------------------ */
    var $tabs = $(".js-tabs");

    if ($tabs.length) {

        var $tab_list = $tabs.find(".js-tablist");
        $tab_list.each(function() {
            var $this_tab_list = $(this),
                options = $this_tab_list.data(),
                $tabs_prefix_classes = typeof options.tabsPrefixClass !== 'undefined' ? options.tabsPrefixClass + '-' : '',
                $hx = typeof options.hx !== 'undefined' ? options.hx : '',
                $existing_hx = typeof options.existingHx !== 'undefined' ? options.existingHx : '',
                $this_tab_list_items = $this_tab_list.children(".js-tablist__item"),
                $this_tab_list_links = $this_tab_list.find(".js-tablist__link");

            // roles init
            $this_tab_list.attr("role", "tablist"); // ul
            $this_tab_list_items.attr("role", "presentation"); // li
            $this_tab_list_links.attr("role", "tab"); // a

            // classes init
            $this_tab_list.addClass($tabs_prefix_classes + 'tabs__list');
            $this_tab_list_items.addClass($tabs_prefix_classes + 'tabs__item');
            $this_tab_list_links.addClass($tabs_prefix_classes + 'tabs__link');

            // controls/tabindex attributes
            $this_tab_list_links.each(function() {
                var $this = $(this),
                    $hx_generated_class = typeof options.tabsGeneratedHxClass !== 'undefined' ? options.tabsGeneratedHxClass : 'invisible',
                    $href = $this.attr("href"),
                    $controls = $($href),
                    $text = $this.text();

                if ($hx !== "") {
                    $controls.prepend('<' + $hx + ' class="' + $hx_generated_class + '" tabindex="0">' + $text + '</' + $hx + '>');
                }
                if ($existing_hx !== "") {
                    $controls.find($existing_hx + ':first-child').attr('tabindex', 0);
                }
                if (typeof $href !== "undefined" && $href !== "" && $href !== "#") {
                    $this.attr({
                        "aria-controls": $href.replace("#", ""),
                        "tabindex": -1,
                        "aria-selected": "false"
                    });
                }

                $this.removeAttr("href");

            });
        });

        /* Tabs content ---------------------------------------------------------------------------------------------------- */
        $(".js-tabcontent").attr({
                "role": "tabpanel", // contents
                "aria-hidden": "true" // all hidden
                //"tabindex": 0
            })
            .each(function() {
                var $this = $(this),
                    $this_id = $this.attr("id"),
                    $prefix_attribute = $("#label_" + $this_id).closest('.js-tablist').attr('data-tabs-prefix-class'),
                    $tabs_prefix_classes = typeof $prefix_attribute !== 'undefined' ? $prefix_attribute + '-' : '';
                // label by link
                $this.attr("aria-labelledby", "label_" + $this_id);

                $this.addClass($tabs_prefix_classes + 'tabs__content');
            });

        // search if hash is ON not disabled tab
        if (hash !== "" && $("#" + hash + ".js-tabcontent").length !== 0) {
            if ($("#label_" + hash + ".js-tablist__link:not([aria-disabled='true'])").length) {
                // display not disabled
                $("#" + hash + ".js-tabcontent").removeAttr("aria-hidden");
                // selection menu
                $("#label_" + hash + ".js-tablist__link").attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });
            }

        }
        // search if hash is IN not disabled tab
        if (hash !== "" && $("#" + hash).parents('.js-tabcontent').length) {
            var $this_hash = $("#" + hash),
                $tab_content_parent = $this_hash.parents('.js-tabcontent'),
                $tab_content_parent_id = $tab_content_parent.attr('id');

            if ($("#label_" + $tab_content_parent_id + ".js-tablist__link:not([aria-disabled='true'])").length) {
                $tab_content_parent.removeAttr("aria-hidden");
                // selection menu
                $("#label_" + $tab_content_parent_id + ".js-tablist__link").attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });
            }
        }

        // if no selected => select first not disabled
        $tabs.each(function() {
            var $this = $(this),
                $tab_selected = $this.find('.js-tablist__link[aria-selected="true"]'),
                $first_link = $this.find('.js-tablist__link:not([aria-disabled="true"]):first'),
                $first_content = $('#' + $first_link.attr('aria-controls'));

            if ($tab_selected.length === 0) {
                $first_link.attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });
                $first_content.removeAttr("aria-hidden");
            }
        });

        /* Events ---------------------------------------------------------------------------------------------------------- */
        /* click on a tab link */
        $("body").on("click", ".js-tablist__link[aria-disabled='true']", function() {
            return false;
        });
        $("body").on("click", ".js-tablist__link:not([aria-disabled='true'])", function(event) {
                var $this = $(this),
                    $hash_to_update = $this.attr("aria-controls"),
                    $tab_content_linked = $("#" + $this.attr("aria-controls")),
                    $parent = $this.closest(".js-tabs"),
                    $all_tab_links = $parent.find(".js-tablist__link"),
                    $all_tab_contents = $parent.find(".js-tabcontent");

                // aria selected false on all links
                $all_tab_links.attr({
                    "tabindex": -1,
                    "aria-selected": "false"
                });

                // add aria selected on $this
                $this.attr({
                    "aria-selected": "true",
                    "tabindex": 0
                });

                // add aria-hidden on all tabs contents
                $all_tab_contents.attr("aria-hidden", "true");

                // remove aria-hidden on tab linked
                $tab_content_linked.removeAttr("aria-hidden");

                // add fragment (timeout for transitions)
                setTimeout(function() {
                    history.pushState(null, null, location.pathname + location.search + '#' + $hash_to_update)
                }, 1000);

                event.preventDefault();
            })
            /* Key down in tabs */
            .on("keydown", ".js-tablist", function(event) {

                var $parent = $(this).closest('.js-tabs'),
                    $activated = $parent.find('.js-tablist__link[aria-selected="true"]').parent(),
                    $last_link = $parent.find('.js-tablist__item:last-child .js-tablist__link'),
                    $first_link = $parent.find('.js-tablist__item:first-child .js-tablist__link'),
                    $focus_on_tab_only = false,
                    $prev = $activated,
                    $next = $activated;

                // search valid previous
                do {
                    // if we are on first => activate last
                    if ($prev.is(".js-tablist__item:first-child")) {
                        $prev = $last_link.parent();
                    }
                    // else previous
                    else {
                        $prev = $prev.prev();
                    }
                }
                while ($prev.children('.js-tablist__link').attr('aria-disabled') === 'true' && $prev !== $activated);

                // search valid next
                do {
                    // if we are on last => activate first
                    if ($next.is(".js-tablist__item:last-child")) {
                        $next = $first_link.parent();
                    }
                    // else previous
                    else {
                        $next = $next.next();
                    }
                }
                while ($next.children('.js-tablist__link').attr('aria-disabled') === 'true' && $next !== $activated);

                // some event should be activated only if the focus is on tabs (not on tabpanel)
                if ($(document.activeElement).is($parent.find('.js-tablist__link'))) {
                    $focus_on_tab_only = true;
                }

                // catch keyboard event only if focus is on tab
                if ($focus_on_tab_only && !event.ctrlKey) {
                    // strike up or left in the tab
                    if (event.keyCode == 37 || event.keyCode == 38) {

                        $prev.children(".js-tablist__link").click().focus();

                        event.preventDefault();
                    }
                    // strike down or right in the tab
                    else if (event.keyCode == 40 || event.keyCode == 39) {

                        $next.children(".js-tablist__link").click().focus();

                        event.preventDefault();
                    } else if (event.keyCode == 36) {
                        // activate first tab
                        $first_link.click().focus();
                        event.preventDefault();
                    } else if (event.keyCode == 35) {
                        // activate last tab
                        $last_link.click().focus();
                        event.preventDefault();
                    }

                }

            })
            .on("keydown", ".js-tabcontent", function(event) {

                var $this = $(this),
                    $selector_tab_to_focus = $this.attr('aria-labelledby'),
                    $tab_to_focus = $("#" + $selector_tab_to_focus),
                    $parent_item = $tab_to_focus.parent(),
                    $parent_list = $parent_item.parent(),
                    $first_item = $parent_list.find('.js-tablist__item:first-child'),
                    $last_item = $parent_list.find('.js-tablist__item:last-child'),
                    $prev_item = $parent_item,
                    $next_item = $parent_item;

                // CTRL up/Left
                if ((event.keyCode == 37 || event.keyCode == 38) && event.ctrlKey) {
                    $tab_to_focus.focus();
                    event.preventDefault();
                }
                // CTRL PageUp
                if (event.keyCode == 33 && event.ctrlKey) {
                    //$tab_to_focus.focus();

                    // search valid previous
                    do {
                        // if we are on first => last
                        if ($prev_item.is(".js-tablist__item:first-child")) {
                            $prev_item = $last_item;
                        }
                        // else previous
                        else {
                            $prev_item = $prev_item.prev();
                        }
                    }
                    while ($prev_item.children('.js-tablist__link').attr('aria-disabled') === 'true' && $prev_item !== $parent_item);

                    $prev_item.children(".js-tablist__link").click().focus();

                    event.preventDefault();
                }
                // CTRL PageDown
                if (event.keyCode == 34 && event.ctrlKey) {
                    $tab_to_focus.focus();

                    // search valid next
                    do {
                        // if we are on last => first
                        if ($next_item.is(".js-tablist__item:last-child")) {
                            $next_item = $first_item;
                        }
                        // else previous
                        else {
                            $next_item = $next_item.next();
                        }
                    }
                    while ($next_item.children('.js-tablist__link').attr('aria-disabled') === 'true' && $next_item !== $parent_item);

                    $next_item.children(".js-tablist__link").click().focus();

                    event.preventDefault();
                }

            })
            /* click on a tab link */
            .on("click", ".js-link-to-tab", function() {
                var $this = $(this),
                    $tab_to_go = $($this.attr('href')),
                    $button_to_click = $('#' + $tab_to_go.attr('aria-labelledby'));

                if ($button_to_click.attr('aria-disabled') !== 'true') {
                    // activate tabs
                    $button_to_click.click();
                    // give focus to the good button
                    setTimeout(function() {
                        $button_to_click.focus()
                    }, 10);
                }

            });

    }

});
<|endoftext|>