<commit_before>define(['@jquery', '@aws', 'conf', 'amzn-login', 'fb',
    'g-plus-one', '@jq-throttle'],
function($, AWS, conf, amazon, FB){

    LoginCtlr.$inject = ['$log', '$rootScope', '$scope', '$http', 'url', 'awsCred'];
    function LoginCtlr($log, $rs, $scope, $http, url, awsCred){

        $rs.chk_cred().then(function(data){
            url.go('poll', 1);
        });

        function login(params, identity) {
            awsCred.login(params, identity).then(function(){
                url.go('poll', 1);
            }, function(err){
                $log.warn(err);
                alert("Oops, login failed somehow");
            })
        }

        function login_amazon_cb(resp) {
            if ( resp['status'] !== 'complete') {
                alert('Login failed');
                return $log.warn(resp);
            }

            $http({
                method: 'GET',
                url: 'https://api.amazon.com/user/profile',
                headers: {
                    'Authorization': 'bearer ' + resp.access_token
                }
            }).then(function(data){

                login({
                    RoleArn: conf.role('aws').arn,
                    ProviderId: 'www.amazon.com',
                    WebIdentityToken: resp['access_token'],
                    DurationSeconds: 3600
                }, data.data.user_id);

            }, function(err){
                $log.warn(err);
            })
        }

        $scope.login_amazon = function() {
            var options = { scope : 'profile' };
            amazon.Login.setClientId(conf.role('aws').client_id);
            amazon.Login.authorize(options, login_amazon_cb);
        }

        function login_facebook_cb(resp) {

            if (resp.status !== 'connected') {
                return FB.login();
            }

            login({
                RoleArn: conf.role('fb').arn,
                ProviderId: 'graph.facebook.com',
                WebIdentityToken: resp.authResponse.accessToken,
                DurationSeconds: 3600
            }, resp.authResponse.userID);
        }

        $scope.login_facebook = function() {
            FB.init({
                appId      : conf.role('fb').app_id,
                status     : true, // check login status
                cookie     : true, // enable cookies to allow the server to access the session
                xfbml      : true  // parse XFBML
            });

            FB.Event.subscribe('auth.authResponseChange', login_facebook_cb);
            FB.login();
        };

        function login_google_cb(authResult) {
            if (!authResult['status']['signed_in']) {
                alert('Login failed');
                return;
            }
            gapi.client.load('plus','v1', function(){
                var request = gapi.client.plus.people.get({
                    'userId': 'me'
                });
                request.execute(function(resp) {
                    login({
                        RoleArn: conf.role('google').arn,
                        WebIdentityToken: authResult.id_token,
                        DurationSeconds: 3600,
                    }, resp.id);
                });
            });
        }

        $scope.login_google = function() {
            gapi.auth.signIn({
                'callback': $.debounce(50, login_google_cb),
                'clientid': conf.role('google').client_id
            });
        }
    }

    return function(module){
        module.controller('LoginCtlr', LoginCtlr);
        return module;
    }
})
<commit_msg>Turned off auth alert in google_cb<commit_after>define(['@jquery', '@aws', 'conf', 'amzn-login', 'fb',
    'g-plus-one', '@jq-throttle'],
function($, AWS, conf, amazon, FB){

    LoginCtlr.$inject = ['$log', '$rootScope', '$scope', '$http', 'url', 'awsCred'];
    function LoginCtlr($log, $rs, $scope, $http, url, awsCred){

        $rs.chk_cred().then(function(data){
            url.go('poll', 1);
        });

        function login(params, identity) {
            awsCred.login(params, identity).then(function(){
                url.go('poll', 1);
            }, function(err){
                $log.warn(err);
                alert("Oops, login failed somehow");
            })
        }

        function login_amazon_cb(resp) {
            if ( resp['status'] !== 'complete') {
                alert('Login failed');
                return $log.warn(resp);
            }

            $http({
                method: 'GET',
                url: 'https://api.amazon.com/user/profile',
                headers: {
                    'Authorization': 'bearer ' + resp.access_token
                }
            }).then(function(data){

                login({
                    RoleArn: conf.role('aws').arn,
                    ProviderId: 'www.amazon.com',
                    WebIdentityToken: resp['access_token'],
                    DurationSeconds: 3600
                }, data.data.user_id);

            }, function(err){
                $log.warn(err);
            })
        }

        $scope.login_amazon = function() {
            var options = { scope : 'profile' };
            amazon.Login.setClientId(conf.role('aws').client_id);
            amazon.Login.authorize(options, login_amazon_cb);
        }

        function login_facebook_cb(resp) {

            if (resp.status !== 'connected') {
                return FB.login();
            }

            login({
                RoleArn: conf.role('fb').arn,
                ProviderId: 'graph.facebook.com',
                WebIdentityToken: resp.authResponse.accessToken,
                DurationSeconds: 3600
            }, resp.authResponse.userID);
        }

        $scope.login_facebook = function() {
            FB.init({
                appId      : conf.role('fb').app_id,
                status     : true, // check login status
                cookie     : true, // enable cookies to allow the server to access the session
                xfbml      : true  // parse XFBML
            });

            FB.Event.subscribe('auth.authResponseChange', login_facebook_cb);
            FB.login();
        };

        function login_google_cb(authResult) {
            $log.warn(authResult);
            if (!authResult['status']['signed_in']) {
                // Besides the end of G+ authentication process,
                // it's also fired when the G+ login page first loads (without cookie)

                return;
            }

            gapi.client.load('plus','v1', function(){
                var request = gapi.client.plus.people.get({
                    'userId': 'me'
                });
                request.execute(function(resp) {
                    login({
                        RoleArn: conf.role('google').arn,
                        WebIdentityToken: authResult.id_token,
                        DurationSeconds: 3600,
                    }, resp.id);
                });
            });
        }

        $scope.login_google = function() {
            gapi.auth.signIn({
                //'callback': $.debounce(50, login_google_cb),
                'callback': login_google_cb,
                'clientid': conf.role('google').client_id
            });
        }
    }

    return function(module){
        module.controller('LoginCtlr', LoginCtlr);
        return module;
    }
})
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

var gDebug, gLog;
var gAnalysisPath = "../../";
var gBzAPIPath = "https://bugzilla.mozilla.org/bzapi/";
var gBzBasePath = "https://bugzilla.mozilla.org/";
var gSocorroPath = "https://crash-stats.mozilla.com/";

// Should select / figure out from https://crash-stats.mozilla.com/api/ProductsVersions/ or https://crash-stats.mozilla.com/api/CurrentVersions/
var gProduct = "Firefox", gVersion = "37.0b3", gProcess = "browser";
var gDate, gDuration = 7;
var gScores = {}, gSocorroAPIToken;

window.onload = function() {
  gDebug = document.getElementById("debug");
  gLog = document.getElementById("debugLog");
  gSocorroAPIToken = getParameterByName("token");

  //if (!gSocorroAPIToken) {
  //  $err = displayMessage("ERROR - you need an API token. Please ");
  //  $link = $err.appendChild(document.createElement("a"));
  //  $link.setAttribute("href", "https://crash-stats.mozilla.com/api/tokens/");
  //  $link.textContent = "create one via Socorro";
  //  $err.appendChild(document.createTextNode(" and hand it over with the ?token=... parameter!"));
  //}
  //else {
    fetchFile(gSocorroPath + "api/CrontabberState/", "json",
      function(aData) {
        if (aData) {
          var matviewTime = new Date(aData.state["signatures-matview"].last_success);
          matviewTime.setDate(matviewTime.getDate() - 1); // subtract one day
          gDate = makeDate(matviewTime);
          document.getElementById("repDate").textContent = gDate;
          document.getElementById("repDuration").textContent = gDuration;
          document.getElementById("repProd").textContent = gProduct;
          document.getElementById("repVer").textContent = gVersion;
          document.getElementById("repPType").textContent = gProcess;

          processData();
        }
        else {
          gDate = null;
          displayMessage("ERROR - couldn't find crobtabber state!");
        }
      }
    );
  //}
}

function processData() {
  var tblBody = document.getElementById("scoreTBody");
  var limit = 10; //300;
  fetchFile(gSocorroPath + "api/TCBS/?product=" + gProduct + "&version=" + gVersion +
            "&crash_type=" + gProcess + "&date_range_type=" + gDuration +
            "&end_date=" + gDate + "&limit=" + limit, "json",
    function(aData) {
      if (aData) {
        var resultCount = aData.crashes.length;
        displayMessage("Processing " + resultCount + " results…");
        for (var i = 0; i <= resultCount - 1; i++) {
          gScores[aData.crashes[i].signature] = aData.crashes[i];
          calcScore(aData.crashes[i].signature, function(aSignature) {
            if (aSignature == aData.crashes[resultCount-1].signature) {
              // last item, so all done with calculating
              buildDataTable();
            }
          });
        }
      }
      else {
        displayMessage("ERROR - couldn't find TCBS data!");
      }
    }
  );
}

function buildDataTable() {
  var msgRow = document.getElementById("message_row");
  if (msgRow) {
    msgRow.parentNode.removeChild(msgRow);
  }
  // Header
  var trow = document.getElementById("scoreTHeader")
                     .appendChild(document.createElement("tr"));
  var cell = trow.appendChild(document.createElement("th"));
  cell.textContent = "Signature";
  var cell = trow.appendChild(document.createElement("th"));
  cell.textContent = "Count";
  var cell = trow.appendChild(document.createElement("th"));
  cell.textContent = "Score";
  // Body
  var tblBody = document.getElementById("scoreTBody");
  var sigSorted = Object.keys(gScores).sort(
    function (a, b) { return gScores[b].score - gScores[a].score; }
  );
  for (var i = 0; i <= sigSorted.length - 1; i++) {
    signature = sigSorted[i];
    var trow = tblBody.appendChild(document.createElement("tr"));
    trow.setAttribute("id", "sdata_" + encodeURIComponent(signature));
    var cell = trow.appendChild(document.createElement("td"));
    cell.classList.add("sig");
    var link = cell.appendChild(document.createElement("a"));
    link.setAttribute("href",
        gSocorroPath + "report/list?product=" + gProduct +
        "&version=" + gProduct + ":" + gVersion +
        "&range_unit=days&range_value=" + gDuration + "&date=" + gDate +
        "&signature=" + encodeURIComponent(signature));
    link.textContent = signature;
    var cell = trow.appendChild(document.createElement("td"));
    cell.classList.add("num");
    cell.textContent = gScores[signature].count;
    var cell = trow.appendChild(document.createElement("td"));
    cell.classList.add("num");
    cell.textContent = parseInt(gScores[signature].score);
  }
}

function calcScore(aSignature, aCallback) {
  gScores[aSignature].score = gScores[aSignature].count;
  // Startup crashes: count each crash with factor 10
  gScores[aSignature].score *= 1 + gScores[aSignature].startup_percent * (10 - 1);
  // GC crashes: count each crash with factor 1/4
  gScores[aSignature].score *= 1 + (gScores[aSignature].is_gc_count * (.25 - 1)) / gScores[aSignature].count;
  // OOM | small: factor 1/10
  if (aSignature == "OOM | small") {
    gScores[aSignature].score *= .1;
  }
  // OOM | large: factor 5
  if (aSignature.startsWith("OOM | large")) {
    gScores[aSignature].score *= 5;
  }

  // Get signature Summary data
  var sigRepTypes = "distinct_install";
  var startDate = new Date(gDate);
  startDate.setDate(startDate.getDate() - gDuration);
  fetchFile(gSocorroPath + "api/SignatureSummary/?versions=" + gProduct + ":" + gVersion +
            "&signature=" + encodeURIComponent(aSignature) +
            "&report_types=" + sigRepTypes +
            "&start_date=" + makeDate(startDate) + "&end_date=" + gDate, "json",
    function(aData) {
      if (aData) {
        gScores[aSignature].installations = aData.reports.distinct_install[0].installations;
        // installations: factor 0 for <3 installs
        if (aData.reports.distinct_install[0].installations < 3) {
          gScores[aSignature].score *= 0;
        }
        // installations: factor up to 2 for few people crashing over and over,
        //                factor 1 for installations == crashes
        // 1+e^(x*-3)*sin(x*pi)*3 - prototyped via http://www.mathe-fa.de/en
        var instRatio = aData.reports.distinct_install[0].installations /
                        aData.reports.distinct_install[0].crashes;
        gScores[aSignature].score *= 1 + 3 * Math.sin(instRatio * Math.PI) * Math.exp(instRatio * -3);
        gScores[aSignature].installations_factor = 1 + 3 * Math.sin(instRatio * Math.PI) * Math.exp(instRatio * -3);
        gScores[aSignature].installations_ratio = instRatio;
      }
      else {
        console.log("ERROR - couldn't find Signature Summary data for " + aSignature + "!");
      }
      aCallback(aSignature);
    }
  );
}

function displayMessage(aErrorMessage) {
  var trow = document.getElementById("scoreTBody")
                     .appendChild(document.createElement('tr'));
  trow.setAttribute("id", "message_row");
  var cell = trow.appendChild(document.createElement('td'));
  cell.textContent = aErrorMessage;
  return cell;
}

function fetchFile(aURL, aFormat, aCallback) {
  var XHR = new XMLHttpRequest();
  XHR.onreadystatechange = function() {
    if (XHR.readyState == 4) {/*
      gLog.appendChild(document.createElement("li"))
          .appendChild(document.createTextNode(aURL + " - " + XHR.status +
                                               " " + XHR.statusText));*/
    }
    if (XHR.readyState == 4 && XHR.status == 200) {
      // so far so good
      if (XHR.responseXML != null && aFormat == "xml" &&
          XHR.responseXML.getElementById('test').firstChild.data)
        aCallback(aXHR.responseXML.getElementById('test').firstChild.data);
      else if (XHR.responseText != null && aFormat == "json")
        aCallback(JSON.parse(XHR.responseText));
      else
        aCallback(XHR.responseText);
    } else if (XHR.readyState == 4 && XHR.status != 200) {
      // fetched the wrong page or network error...
      console.log("ERROR: XHR status " + XHR.status + " - " + aURL);
      aCallback(null);
    }
  };
  XHR.open("GET", aURL);
  if (gSocorroAPIToken) {
    // XXX: Should work but doesn't yet! I need to talk to peterbe about that.
    //      Use this path when we have a token so bug 1xxxxxx can be tested.
    XHR.setRequestHeader("Auth-Token", gSocorroAPIToken);
  }
  if (aFormat == "json") { XHR.setRequestHeader("Accept", "application/json"); }
  else if (aFormat == "xml") { XHR.setRequestHeader("Accept", "application/xml"); }
  try {
    XHR.send();
  }
  catch (e) {
    console.log("ERROR: XHR send - " + e + " - " + aURL);
    aCallback(null);
  }
}

function makeDate(aDate) {
  // Date format is YYYY-MM-DD
  // Note that .getMonth() returns a number between 0 and 11 (0 for January)!
  return aDate.getUTCFullYear() + "-" +
         (aDate.getUTCMonth() < 9 ? "0" : "") + (aDate.getUTCMonth() + 1 ) + "-" +
         (aDate.getUTCDate() < 10 ? "0" : "") + aDate.getUTCDate();
}

function getParameterByName(aName) {
  // from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
  name = aName.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
      results = regex.exec(location.search);
  return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
<commit_msg>put actual bug number for the token issue into the code<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

var gDebug, gLog;
var gAnalysisPath = "../../";
var gBzAPIPath = "https://bugzilla.mozilla.org/bzapi/";
var gBzBasePath = "https://bugzilla.mozilla.org/";
var gSocorroPath = "https://crash-stats.mozilla.com/";

// Should select / figure out from https://crash-stats.mozilla.com/api/ProductsVersions/ or https://crash-stats.mozilla.com/api/CurrentVersions/
var gProduct = "Firefox", gVersion = "37.0b3", gProcess = "browser";
var gDate, gDuration = 7;
var gScores = {}, gSocorroAPIToken;

window.onload = function() {
  gDebug = document.getElementById("debug");
  gLog = document.getElementById("debugLog");
  gSocorroAPIToken = getParameterByName("token");

  //if (!gSocorroAPIToken) {
  //  $err = displayMessage("ERROR - you need an API token. Please ");
  //  $link = $err.appendChild(document.createElement("a"));
  //  $link.setAttribute("href", "https://crash-stats.mozilla.com/api/tokens/");
  //  $link.textContent = "create one via Socorro";
  //  $err.appendChild(document.createTextNode(" and hand it over with the ?token=... parameter!"));
  //}
  //else {
    fetchFile(gSocorroPath + "api/CrontabberState/", "json",
      function(aData) {
        if (aData) {
          var matviewTime = new Date(aData.state["signatures-matview"].last_success);
          matviewTime.setDate(matviewTime.getDate() - 1); // subtract one day
          gDate = makeDate(matviewTime);
          document.getElementById("repDate").textContent = gDate;
          document.getElementById("repDuration").textContent = gDuration;
          document.getElementById("repProd").textContent = gProduct;
          document.getElementById("repVer").textContent = gVersion;
          document.getElementById("repPType").textContent = gProcess;

          processData();
        }
        else {
          gDate = null;
          displayMessage("ERROR - couldn't find crobtabber state!");
        }
      }
    );
  //}
}

function processData() {
  var tblBody = document.getElementById("scoreTBody");
  var limit = 10; //300;
  fetchFile(gSocorroPath + "api/TCBS/?product=" + gProduct + "&version=" + gVersion +
            "&crash_type=" + gProcess + "&date_range_type=" + gDuration +
            "&end_date=" + gDate + "&limit=" + limit, "json",
    function(aData) {
      if (aData) {
        var resultCount = aData.crashes.length;
        displayMessage("Processing " + resultCount + " results…");
        for (var i = 0; i <= resultCount - 1; i++) {
          gScores[aData.crashes[i].signature] = aData.crashes[i];
          calcScore(aData.crashes[i].signature, function(aSignature) {
            if (aSignature == aData.crashes[resultCount-1].signature) {
              // last item, so all done with calculating
              buildDataTable();
            }
          });
        }
      }
      else {
        displayMessage("ERROR - couldn't find TCBS data!");
      }
    }
  );
}

function buildDataTable() {
  var msgRow = document.getElementById("message_row");
  if (msgRow) {
    msgRow.parentNode.removeChild(msgRow);
  }
  // Header
  var trow = document.getElementById("scoreTHeader")
                     .appendChild(document.createElement("tr"));
  var cell = trow.appendChild(document.createElement("th"));
  cell.textContent = "Signature";
  var cell = trow.appendChild(document.createElement("th"));
  cell.textContent = "Count";
  var cell = trow.appendChild(document.createElement("th"));
  cell.textContent = "Score";
  // Body
  var tblBody = document.getElementById("scoreTBody");
  var sigSorted = Object.keys(gScores).sort(
    function (a, b) { return gScores[b].score - gScores[a].score; }
  );
  for (var i = 0; i <= sigSorted.length - 1; i++) {
    signature = sigSorted[i];
    var trow = tblBody.appendChild(document.createElement("tr"));
    trow.setAttribute("id", "sdata_" + encodeURIComponent(signature));
    var cell = trow.appendChild(document.createElement("td"));
    cell.classList.add("sig");
    var link = cell.appendChild(document.createElement("a"));
    link.setAttribute("href",
        gSocorroPath + "report/list?product=" + gProduct +
        "&version=" + gProduct + ":" + gVersion +
        "&range_unit=days&range_value=" + gDuration + "&date=" + gDate +
        "&signature=" + encodeURIComponent(signature));
    link.textContent = signature;
    var cell = trow.appendChild(document.createElement("td"));
    cell.classList.add("num");
    cell.textContent = gScores[signature].count;
    var cell = trow.appendChild(document.createElement("td"));
    cell.classList.add("num");
    cell.textContent = parseInt(gScores[signature].score);
  }
}

function calcScore(aSignature, aCallback) {
  gScores[aSignature].score = gScores[aSignature].count;
  // Startup crashes: count each crash with factor 10
  gScores[aSignature].score *= 1 + gScores[aSignature].startup_percent * (10 - 1);
  // GC crashes: count each crash with factor 1/4
  gScores[aSignature].score *= 1 + (gScores[aSignature].is_gc_count * (.25 - 1)) / gScores[aSignature].count;
  // OOM | small: factor 1/10
  if (aSignature == "OOM | small") {
    gScores[aSignature].score *= .1;
  }
  // OOM | large: factor 5
  if (aSignature.startsWith("OOM | large")) {
    gScores[aSignature].score *= 5;
  }

  // Get signature Summary data
  var sigRepTypes = "distinct_install";
  var startDate = new Date(gDate);
  startDate.setDate(startDate.getDate() - gDuration);
  fetchFile(gSocorroPath + "api/SignatureSummary/?versions=" + gProduct + ":" + gVersion +
            "&signature=" + encodeURIComponent(aSignature) +
            "&report_types=" + sigRepTypes +
            "&start_date=" + makeDate(startDate) + "&end_date=" + gDate, "json",
    function(aData) {
      if (aData) {
        gScores[aSignature].installations = aData.reports.distinct_install[0].installations;
        // installations: factor 0 for <3 installs
        if (aData.reports.distinct_install[0].installations < 3) {
          gScores[aSignature].score *= 0;
        }
        // installations: factor up to 2 for few people crashing over and over,
        //                factor 1 for installations == crashes
        // 1+e^(x*-3)*sin(x*pi)*3 - prototyped via http://www.mathe-fa.de/en
        var instRatio = aData.reports.distinct_install[0].installations /
                        aData.reports.distinct_install[0].crashes;
        gScores[aSignature].score *= 1 + 3 * Math.sin(instRatio * Math.PI) * Math.exp(instRatio * -3);
        gScores[aSignature].installations_factor = 1 + 3 * Math.sin(instRatio * Math.PI) * Math.exp(instRatio * -3);
        gScores[aSignature].installations_ratio = instRatio;
      }
      else {
        console.log("ERROR - couldn't find Signature Summary data for " + aSignature + "!");
      }
      aCallback(aSignature);
    }
  );
}

function displayMessage(aErrorMessage) {
  var trow = document.getElementById("scoreTBody")
                     .appendChild(document.createElement('tr'));
  trow.setAttribute("id", "message_row");
  var cell = trow.appendChild(document.createElement('td'));
  cell.textContent = aErrorMessage;
  return cell;
}

function fetchFile(aURL, aFormat, aCallback) {
  var XHR = new XMLHttpRequest();
  XHR.onreadystatechange = function() {
    if (XHR.readyState == 4) {/*
      gLog.appendChild(document.createElement("li"))
          .appendChild(document.createTextNode(aURL + " - " + XHR.status +
                                               " " + XHR.statusText));*/
    }
    if (XHR.readyState == 4 && XHR.status == 200) {
      // so far so good
      if (XHR.responseXML != null && aFormat == "xml" &&
          XHR.responseXML.getElementById('test').firstChild.data)
        aCallback(aXHR.responseXML.getElementById('test').firstChild.data);
      else if (XHR.responseText != null && aFormat == "json")
        aCallback(JSON.parse(XHR.responseText));
      else
        aCallback(XHR.responseText);
    } else if (XHR.readyState == 4 && XHR.status != 200) {
      // fetched the wrong page or network error...
      console.log("ERROR: XHR status " + XHR.status + " - " + aURL);
      aCallback(null);
    }
  };
  XHR.open("GET", aURL);
  if (gSocorroAPIToken) {
    // XXX: Should work but doesn't yet! We'll need to figure this out.
    //      Use this path when we have a token so bug 1143424 can be tested.
    XHR.setRequestHeader("Auth-Token", gSocorroAPIToken);
  }
  if (aFormat == "json") { XHR.setRequestHeader("Accept", "application/json"); }
  else if (aFormat == "xml") { XHR.setRequestHeader("Accept", "application/xml"); }
  try {
    XHR.send();
  }
  catch (e) {
    console.log("ERROR: XHR send - " + e + " - " + aURL);
    aCallback(null);
  }
}

function makeDate(aDate) {
  // Date format is YYYY-MM-DD
  // Note that .getMonth() returns a number between 0 and 11 (0 for January)!
  return aDate.getUTCFullYear() + "-" +
         (aDate.getUTCMonth() < 9 ? "0" : "") + (aDate.getUTCMonth() + 1 ) + "-" +
         (aDate.getUTCDate() < 10 ? "0" : "") + aDate.getUTCDate();
}

function getParameterByName(aName) {
  // from http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
  name = aName.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
      results = regex.exec(location.search);
  return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
<|endoftext|>


<commit_before>$(function() {
    $("#resource1").modal('show');
});<commit_msg>adding resources modal<commit_after>$(function() {
    $("resource1").click(function() {
        $("#resourceModal1").modal('show');
    });
});<|endoftext|>


<commit_before>/*======================================================
************   Searchbar   ************
======================================================*/
app.initSearchbar = function (pageContainer) {
    pageContainer = $(pageContainer);
    var searchbar = pageContainer.hasClass('searchbar') ? pageContainer : pageContainer.find('.searchbar');
    if (searchbar.length === 0) return;
    if (!pageContainer.hasClass('page')) pageContainer = searchbar.parents('.page').eq(0);
    var searchbarOverlay = pageContainer.hasClass('page') ? pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
    var input = searchbar.find('input[type="search"]');
    var clear = searchbar.find('.searchbar-clear');
    var cancel = searchbar.find('.searchbar-cancel');
    var searchList = $(searchbar.attr('data-search-list'));
    var isVirtualList = searchList.hasClass('virtual-list');
    var virtualList;
    var searchIn = searchbar.attr('data-search-in');
    var searchBy = searchbar.attr('data-search-by');
    var found = searchbar.attr('data-searchbar-found');
    if (!found) {
        found = pageContainer.find('.searchbar-found');
        if (found.length === 0) found = $('.searchbar-found');
    }
    else {
        found = $(found);
    }
    var notFound = searchbar.attr('data-searchbar-not-found');
    if (!notFound) {
        notFound = pageContainer.find('.searchbar-not-found');
        if (notFound.length === 0) notFound = $('.searchbar-not-found');
    }
    else {
        notFound = $(notFound);
    }

    // Cancel button
    var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
    if (cancel.length > 0) {
        cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');
    }

    // Handlers
    function disableSearchbar() {
        input.val('').trigger('change');
        searchbar.removeClass('searchbar-active searchbar-not-empty');
        if (cancel.length > 0) cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');

        if (searchList) searchbarOverlay.removeClass('searchbar-overlay-active');
        if (app.device.ios) {
            setTimeout(function () {
                input.blur();
                searchList.trigger('disableSearch');
            }, 400);
        }
        else {
            input.blur();
            searchList.trigger('disableSearch');
        }
    }

    // Activate
    function enableSearchbar() {
        if (app.device.ios) {
            setTimeout(function () {
                if (searchList && !searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
                searchbar.addClass('searchbar-active');
                if (cancel.length > 0) cancel.css(cancelMarginProp, '0px');
                searchList.trigger('enableSearch');

            }, 400);
        }
        else {
            if (searchList && !searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
            searchbar.addClass('searchbar-active');
            if (cancel.length > 0) cancel.css(cancelMarginProp, '0px');
            searchList.trigger('enableSearch');
        }
    }

    // Clear
    function clearSearchbar() {
        input.val('').trigger('change').focus();
        searchList.trigger('clearSearch');
    }

    // Change
    function searchValue() {
        setTimeout(function () {
            var value = input.val().trim();
            if (value.length === 0) {
                searchbar.removeClass('searchbar-not-empty');
                if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
            }
            else {
                searchbar.addClass('searchbar-not-empty');
                if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.removeClass('searchbar-overlay-active');
            }
            if (searchList.length > 0 && (searchIn || isVirtualList)) search(value);
        }, 0);
    }

    //Prevent submit
    function preventSubmit(e) {
        e.preventDefault();
    }

    function attachEvents(destroy) {
        var method = destroy ? 'off' : 'on';
        searchbar[method]('submit', preventSubmit);
        cancel[method]('click', disableSearchbar);
        searchbarOverlay[method]('click', disableSearchbar);
        input[method]('focus', enableSearchbar);
        input[method]('change keydown keypress keyup', searchValue);
        clear[method]('click', clearSearchbar);
    }
    function detachEvents() {
        attachEvents(true);
    }
    searchbar[0].f7DestroySearchbar = detachEvents;

    // Attach events
    attachEvents();

    // Search
    function search(query) {
        var values = query.trim().toLowerCase().split(' ');
        var foundItems = [];
        if (isVirtualList) {
            virtualList = searchList[0].f7VirtualList;
            if (query.trim() === '') {
                virtualList.resetFilter();
                notFound.hide();
                found.show();
                return;
            }
            if (virtualList.params.searchAll) {
                foundItems = virtualList.params.searchAll(query, virtualList.items) || [];
            }
            else if (virtualList.params.searchByItem) {
                for (var i = 0; i < virtualList.items.length; i++) {
                    if(virtualList.params.searchByItem(query, i, virtualList.params.items[i])) {
                        foundItems.push(i);
                    }
                }
            }
        }
        else {
            searchList.find('li').removeClass('hidden-by-searchbar').each(function (index, el) {
                el = $(el);
                var compareWithEl = el.find(searchIn);
                if (compareWithEl.length === 0) return;
                var compareWith;
                compareWith = compareWithEl.text().trim().toLowerCase();
                var wordsMatch = 0;
                for (var i = 0; i < values.length; i++) {
                    if (compareWith.indexOf(values[i]) >= 0) wordsMatch++;
                }
                if (wordsMatch !== values.length) {
                    el.addClass('hidden-by-searchbar');
                }
                else {
                    foundItems.push(el[0]);
                }
            });

            if (app.params.searchbarHideDividers) {
                searchList.find('.item-divider, .list-group-title').each(function () {
                    var title = $(this);
                    var nextElements = title.nextAll('li');
                    var hide = true;
                    for (var i = 0; i < nextElements.length; i++) {
                        var nextEl = $(nextElements[i]);
                        if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
                        if (!nextEl.hasClass('hidden-by-searchbar')) {
                            hide = false;
                        }
                    }
                    if (hide) title.addClass('hidden-by-searchbar');
                    else title.removeClass('hidden-by-searchbar');
                });
            }
            if (app.params.searchbarHideGroups) {
                searchList.find('.list-group').each(function () {
                    var group = $(this);
                    var notHidden = group.find('li:not(.hidden-by-searchbar)');
                    if (notHidden.length === 0) {
                        group.addClass('hidden-by-searchbar');
                    }
                    else {
                        group.removeClass('hidden-by-searchbar');
                    }
                });
            }
        }
        searchList.trigger('search', {query: query, foundItems: foundItems});
        if (foundItems.length === 0) {
            notFound.show();
            found.hide();
        }
        else {
            notFound.hide();
            found.show();
        }
        if (isVirtualList) {
            virtualList.filter(foundItems);
        }
    }

    // Destroy on page remove
    function pageBeforeRemove() {
        detachEvents();
        pageContainer.off('pageBeforeRemove', pageBeforeRemove);
    }
    if (pageContainer.hasClass('page')) {
        pageContainer.on('pageBeforeRemove', pageBeforeRemove);
    }

};
app.destroySearchbar = function (pageContainer) {
    pageContainer = $(pageContainer);
    var searchbar = pageContainer.hasClass('searchbar') ? pageContainer : pageContainer.find('.searchbar');
    if (searchbar.length === 0) return;
    if (searchbar[0].f7DestroySearchbar) searchbar[0].f7DestroySearchbar();
};
<commit_msg>Rename .filter to .filterItems<commit_after>/*======================================================
************   Searchbar   ************
======================================================*/
app.initSearchbar = function (pageContainer) {
    pageContainer = $(pageContainer);
    var searchbar = pageContainer.hasClass('searchbar') ? pageContainer : pageContainer.find('.searchbar');
    if (searchbar.length === 0) return;
    if (!pageContainer.hasClass('page')) pageContainer = searchbar.parents('.page').eq(0);
    var searchbarOverlay = pageContainer.hasClass('page') ? pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
    var input = searchbar.find('input[type="search"]');
    var clear = searchbar.find('.searchbar-clear');
    var cancel = searchbar.find('.searchbar-cancel');
    var searchList = $(searchbar.attr('data-search-list'));
    var isVirtualList = searchList.hasClass('virtual-list');
    var virtualList;
    var searchIn = searchbar.attr('data-search-in');
    var searchBy = searchbar.attr('data-search-by');
    var found = searchbar.attr('data-searchbar-found');
    if (!found) {
        found = pageContainer.find('.searchbar-found');
        if (found.length === 0) found = $('.searchbar-found');
    }
    else {
        found = $(found);
    }
    var notFound = searchbar.attr('data-searchbar-not-found');
    if (!notFound) {
        notFound = pageContainer.find('.searchbar-not-found');
        if (notFound.length === 0) notFound = $('.searchbar-not-found');
    }
    else {
        notFound = $(notFound);
    }

    // Cancel button
    var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
    if (cancel.length > 0) {
        cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');
    }

    // Handlers
    function disableSearchbar() {
        input.val('').trigger('change');
        searchbar.removeClass('searchbar-active searchbar-not-empty');
        if (cancel.length > 0) cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');

        if (searchList) searchbarOverlay.removeClass('searchbar-overlay-active');
        if (app.device.ios) {
            setTimeout(function () {
                input.blur();
                searchList.trigger('disableSearch');
            }, 400);
        }
        else {
            input.blur();
            searchList.trigger('disableSearch');
        }
    }

    // Activate
    function enableSearchbar() {
        if (app.device.ios) {
            setTimeout(function () {
                if (searchList && !searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
                searchbar.addClass('searchbar-active');
                if (cancel.length > 0) cancel.css(cancelMarginProp, '0px');
                searchList.trigger('enableSearch');

            }, 400);
        }
        else {
            if (searchList && !searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
            searchbar.addClass('searchbar-active');
            if (cancel.length > 0) cancel.css(cancelMarginProp, '0px');
            searchList.trigger('enableSearch');
        }
    }

    // Clear
    function clearSearchbar() {
        input.val('').trigger('change').focus();
        searchList.trigger('clearSearch');
    }

    // Change
    function searchValue() {
        setTimeout(function () {
            var value = input.val().trim();
            if (value.length === 0) {
                searchbar.removeClass('searchbar-not-empty');
                if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
            }
            else {
                searchbar.addClass('searchbar-not-empty');
                if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.removeClass('searchbar-overlay-active');
            }
            if (searchList.length > 0 && (searchIn || isVirtualList)) search(value);
        }, 0);
    }

    //Prevent submit
    function preventSubmit(e) {
        e.preventDefault();
    }

    function attachEvents(destroy) {
        var method = destroy ? 'off' : 'on';
        searchbar[method]('submit', preventSubmit);
        cancel[method]('click', disableSearchbar);
        searchbarOverlay[method]('click', disableSearchbar);
        input[method]('focus', enableSearchbar);
        input[method]('change keydown keypress keyup', searchValue);
        clear[method]('click', clearSearchbar);
    }
    function detachEvents() {
        attachEvents(true);
    }
    searchbar[0].f7DestroySearchbar = detachEvents;

    // Attach events
    attachEvents();

    // Search
    function search(query) {
        var values = query.trim().toLowerCase().split(' ');
        var foundItems = [];
        if (isVirtualList) {
            virtualList = searchList[0].f7VirtualList;
            if (query.trim() === '') {
                virtualList.resetFilter();
                notFound.hide();
                found.show();
                return;
            }
            if (virtualList.params.searchAll) {
                foundItems = virtualList.params.searchAll(query, virtualList.items) || [];
            }
            else if (virtualList.params.searchByItem) {
                for (var i = 0; i < virtualList.items.length; i++) {
                    if(virtualList.params.searchByItem(query, i, virtualList.params.items[i])) {
                        foundItems.push(i);
                    }
                }
            }
        }
        else {
            searchList.find('li').removeClass('hidden-by-searchbar').each(function (index, el) {
                el = $(el);
                var compareWithEl = el.find(searchIn);
                if (compareWithEl.length === 0) return;
                var compareWith;
                compareWith = compareWithEl.text().trim().toLowerCase();
                var wordsMatch = 0;
                for (var i = 0; i < values.length; i++) {
                    if (compareWith.indexOf(values[i]) >= 0) wordsMatch++;
                }
                if (wordsMatch !== values.length) {
                    el.addClass('hidden-by-searchbar');
                }
                else {
                    foundItems.push(el[0]);
                }
            });

            if (app.params.searchbarHideDividers) {
                searchList.find('.item-divider, .list-group-title').each(function () {
                    var title = $(this);
                    var nextElements = title.nextAll('li');
                    var hide = true;
                    for (var i = 0; i < nextElements.length; i++) {
                        var nextEl = $(nextElements[i]);
                        if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
                        if (!nextEl.hasClass('hidden-by-searchbar')) {
                            hide = false;
                        }
                    }
                    if (hide) title.addClass('hidden-by-searchbar');
                    else title.removeClass('hidden-by-searchbar');
                });
            }
            if (app.params.searchbarHideGroups) {
                searchList.find('.list-group').each(function () {
                    var group = $(this);
                    var notHidden = group.find('li:not(.hidden-by-searchbar)');
                    if (notHidden.length === 0) {
                        group.addClass('hidden-by-searchbar');
                    }
                    else {
                        group.removeClass('hidden-by-searchbar');
                    }
                });
            }
        }
        searchList.trigger('search', {query: query, foundItems: foundItems});
        if (foundItems.length === 0) {
            notFound.show();
            found.hide();
        }
        else {
            notFound.hide();
            found.show();
        }
        if (isVirtualList) {
            virtualList.filterItems(foundItems);
        }
    }

    // Destroy on page remove
    function pageBeforeRemove() {
        detachEvents();
        pageContainer.off('pageBeforeRemove', pageBeforeRemove);
    }
    if (pageContainer.hasClass('page')) {
        pageContainer.on('pageBeforeRemove', pageBeforeRemove);
    }

};
app.destroySearchbar = function (pageContainer) {
    pageContainer = $(pageContainer);
    var searchbar = pageContainer.hasClass('searchbar') ? pageContainer : pageContainer.find('.searchbar');
    if (searchbar.length === 0) return;
    if (searchbar[0].f7DestroySearchbar) searchbar[0].f7DestroySearchbar();
};
<|endoftext|>


<commit_before>  function isNumber(n) {
    return typeof n === 'number' && !isNaN(n);
  }

  function isUndefined(n) {
    return typeof n === 'undefined';
  }

  function toArray(obj, offset) {
    var args = [];

    // This is necessary for IE8
    if (isNumber(offset)) {
      args.push(offset);
    }

    return args.slice.apply(obj, args);
  }

  // Custom proxy to avoid jQuery's guid
  function proxy(fn, context) {
    var args = toArray(arguments, 2);

    return function () {
      return fn.apply(context, args.concat(toArray(arguments)));
    };
  }

  function isCrossOriginURL(url) {
    var parts = url.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);

    return parts && (
      parts[1] !== location.protocol ||
      parts[2] !== location.hostname ||
      parts[3] !== location.port
    );
  }

  function addTimestamp(url) {
    var timestamp = 'timestamp=' + (new Date()).getTime();

    return (url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp);
  }

  function getCrossOrigin(crossOrigin) {
    return crossOrigin ? ' crossOrigin="' + crossOrigin + '"' : '';
  }

  function getImageSize(image, callback) {
    var newImage;

    // Modern browsers (ignore Safari, #120 & #509)
    if (image.naturalWidth && !IS_SAFARI) {
      return callback(image.naturalWidth, image.naturalHeight);
    }

    // IE8: Don't use `new Image()` here (#319)
    newImage = document.createElement('img');

    newImage.onload = function () {
      callback(this.width, this.height);
    };

    newImage.src = image.src;
  }

  function getTransform(options) {
    var transforms = [];
    var rotate = options.rotate;
    var scaleX = options.scaleX;
    var scaleY = options.scaleY;

    if (isNumber(rotate)) {
      transforms.push('rotate(' + rotate + 'deg)');
    }

    if (isNumber(scaleX) && isNumber(scaleY)) {
      transforms.push('scale(' + scaleX + ',' + scaleY + ')');
    }

    return transforms.length ? transforms.join(' ') : 'none';
  }

  function getRotatedSizes(data, isReversed) {
    var deg = abs(data.degree) % 180;
    var arc = (deg > 90 ? (180 - deg) : deg) * Math.PI / 180;
    var sinArc = sin(arc);
    var cosArc = cos(arc);
    var width = data.width;
    var height = data.height;
    var aspectRatio = data.aspectRatio;
    var newWidth;
    var newHeight;

    if (!isReversed) {
      newWidth = width * cosArc + height * sinArc;
      newHeight = width * sinArc + height * cosArc;
    } else {
      newWidth = width / (cosArc + sinArc / aspectRatio);
      newHeight = newWidth / aspectRatio;
    }

    return {
      width: newWidth,
      height: newHeight
    };
  }

  function getSourceCanvas(image, data) {
    var canvas = $('<canvas>')[0];
    var context = canvas.getContext('2d');
    var x = 0;
    var y = 0;
    var width = data.naturalWidth;
    var height = data.naturalHeight;
    var rotate = data.rotate;
    var scaleX = data.scaleX;
    var scaleY = data.scaleY;
    var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1);
    var rotatable = isNumber(rotate) && rotate !== 0;
    var advanced = rotatable || scalable;
    var canvasWidth = width;
    var canvasHeight = height;
    var translateX;
    var translateY;
    var rotated;

    if (scalable) {
      translateX = width / 2;
      translateY = height / 2;
    }

    if (rotatable) {
      rotated = getRotatedSizes({
        width: width,
        height: height,
        degree: rotate
      });

      canvasWidth = rotated.width;
      canvasHeight = rotated.height;
      translateX = rotated.width / 2;
      translateY = rotated.height / 2;
    }

    canvas.width = canvasWidth;
    canvas.height = canvasHeight;

    if (advanced) {
      x = -width / 2;
      y = -height / 2;

      context.save();
      context.translate(translateX, translateY);
    }

    if (rotatable) {
      context.rotate(rotate * Math.PI / 180);
    }

    // Should call `scale` after rotated
    if (scalable) {
      context.scale(scaleX, scaleY);
    }

    context.drawImage(image, floor(x), floor(y), floor(width), floor(height));

    if (advanced) {
      context.restore();
    }

    return canvas;
  }

  function getTouchesCenter(touches) {
    var length = touches.length;
    var pageX = 0;
    var pageY = 0;

    if (length) {
      $.each(touches, function (i, touch) {
        pageX += touch.pageX;
        pageY += touch.pageY;
      });

      pageX /= length;
      pageY /= length;
    }

    return {
      pageX: pageX,
      pageY: pageY
    };
  }

  function getStringFromCharCode(dataView, start, length) {
    var str = '';
    var i;

    for (i = start, length += start; i < length; i++) {
      str += fromCharCode(dataView.getUint8(i));
    }

    return str;
  }

  function getOrientation(arrayBuffer) {
    var dataView = new DataView(arrayBuffer);
    var length = dataView.byteLength;
    var orientation;
    var exifIDCode;
    var tiffOffset;
    var firstIFDOffset;
    var littleEndian;
    var endianness;
    var app1Start;
    var ifdStart;
    var offset;
    var i;

    // Only handle JPEG image (start by 0xFFD8)
    if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
      offset = 2;

      while (offset < length) {
        if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
          app1Start = offset;
          break;
        }

        offset++;
      }
    }

    if (app1Start) {
      exifIDCode = app1Start + 4;
      tiffOffset = app1Start + 10;

      if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
        endianness = dataView.getUint16(tiffOffset);
        littleEndian = endianness === 0x4949;

        if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
          if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
            firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);

            if (firstIFDOffset >= 0x00000008) {
              ifdStart = tiffOffset + firstIFDOffset;
            }
          }
        }
      }
    }

    if (ifdStart) {
      length = dataView.getUint16(ifdStart, littleEndian);

      for (i = 0; i < length; i++) {
        offset = ifdStart + i * 12 + 2;

        if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {

          // 8 is the offset of the current tag's value
          offset += 8;

          // Get the original orientation value
          orientation = dataView.getUint16(offset, littleEndian);

          // Override the orientation with the default value: 1
          dataView.setUint16(offset, 1, littleEndian);
          break;
        }
      }
    }

    return orientation;
  }

  function dataURLToArrayBuffer(dataURL) {
    var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');
    var binary = atob(base64);
    var length = binary.length;
    var arrayBuffer = new ArrayBuffer(length);
    var dataView = new Uint8Array(arrayBuffer);
    var i;

    for (i = 0; i < length; i++) {
      dataView[i] = binary.charCodeAt(i);
    }

    return arrayBuffer;
  }

  // Only available for JPEG image
  function arrayBufferToDataURL(arrayBuffer) {
    var dataView = new Uint8Array(arrayBuffer);
    var length = dataView.length;
    var base64 = '';
    var i;

    for (i = 0; i < length; i++) {
      base64 += fromCharCode(dataView[i]);
    }

    return 'data:image/jpeg;base64,' + btoa(base64);
  }
<commit_msg>Not to override Orientation value to avoid side effect<commit_after>  function isNumber(n) {
    return typeof n === 'number' && !isNaN(n);
  }

  function isUndefined(n) {
    return typeof n === 'undefined';
  }

  function toArray(obj, offset) {
    var args = [];

    // This is necessary for IE8
    if (isNumber(offset)) {
      args.push(offset);
    }

    return args.slice.apply(obj, args);
  }

  // Custom proxy to avoid jQuery's guid
  function proxy(fn, context) {
    var args = toArray(arguments, 2);

    return function () {
      return fn.apply(context, args.concat(toArray(arguments)));
    };
  }

  function isCrossOriginURL(url) {
    var parts = url.match(/^(https?:)\/\/([^\:\/\?#]+):?(\d*)/i);

    return parts && (
      parts[1] !== location.protocol ||
      parts[2] !== location.hostname ||
      parts[3] !== location.port
    );
  }

  function addTimestamp(url) {
    var timestamp = 'timestamp=' + (new Date()).getTime();

    return (url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp);
  }

  function getCrossOrigin(crossOrigin) {
    return crossOrigin ? ' crossOrigin="' + crossOrigin + '"' : '';
  }

  function getImageSize(image, callback) {
    var newImage;

    // Modern browsers (ignore Safari, #120 & #509)
    if (image.naturalWidth && !IS_SAFARI) {
      return callback(image.naturalWidth, image.naturalHeight);
    }

    // IE8: Don't use `new Image()` here (#319)
    newImage = document.createElement('img');

    newImage.onload = function () {
      callback(this.width, this.height);
    };

    newImage.src = image.src;
  }

  function getTransform(options) {
    var transforms = [];
    var rotate = options.rotate;
    var scaleX = options.scaleX;
    var scaleY = options.scaleY;

    if (isNumber(rotate)) {
      transforms.push('rotate(' + rotate + 'deg)');
    }

    if (isNumber(scaleX) && isNumber(scaleY)) {
      transforms.push('scale(' + scaleX + ',' + scaleY + ')');
    }

    return transforms.length ? transforms.join(' ') : 'none';
  }

  function getRotatedSizes(data, isReversed) {
    var deg = abs(data.degree) % 180;
    var arc = (deg > 90 ? (180 - deg) : deg) * Math.PI / 180;
    var sinArc = sin(arc);
    var cosArc = cos(arc);
    var width = data.width;
    var height = data.height;
    var aspectRatio = data.aspectRatio;
    var newWidth;
    var newHeight;

    if (!isReversed) {
      newWidth = width * cosArc + height * sinArc;
      newHeight = width * sinArc + height * cosArc;
    } else {
      newWidth = width / (cosArc + sinArc / aspectRatio);
      newHeight = newWidth / aspectRatio;
    }

    return {
      width: newWidth,
      height: newHeight
    };
  }

  function getSourceCanvas(image, data) {
    var canvas = $('<canvas>')[0];
    var context = canvas.getContext('2d');
    var x = 0;
    var y = 0;
    var width = data.naturalWidth;
    var height = data.naturalHeight;
    var rotate = data.rotate;
    var scaleX = data.scaleX;
    var scaleY = data.scaleY;
    var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1);
    var rotatable = isNumber(rotate) && rotate !== 0;
    var advanced = rotatable || scalable;
    var canvasWidth = width;
    var canvasHeight = height;
    var translateX;
    var translateY;
    var rotated;

    if (scalable) {
      translateX = width / 2;
      translateY = height / 2;
    }

    if (rotatable) {
      rotated = getRotatedSizes({
        width: width,
        height: height,
        degree: rotate
      });

      canvasWidth = rotated.width;
      canvasHeight = rotated.height;
      translateX = rotated.width / 2;
      translateY = rotated.height / 2;
    }

    canvas.width = canvasWidth;
    canvas.height = canvasHeight;

    if (advanced) {
      x = -width / 2;
      y = -height / 2;

      context.save();
      context.translate(translateX, translateY);
    }

    if (rotatable) {
      context.rotate(rotate * Math.PI / 180);
    }

    // Should call `scale` after rotated
    if (scalable) {
      context.scale(scaleX, scaleY);
    }

    context.drawImage(image, floor(x), floor(y), floor(width), floor(height));

    if (advanced) {
      context.restore();
    }

    return canvas;
  }

  function getTouchesCenter(touches) {
    var length = touches.length;
    var pageX = 0;
    var pageY = 0;

    if (length) {
      $.each(touches, function (i, touch) {
        pageX += touch.pageX;
        pageY += touch.pageY;
      });

      pageX /= length;
      pageY /= length;
    }

    return {
      pageX: pageX,
      pageY: pageY
    };
  }

  function getStringFromCharCode(dataView, start, length) {
    var str = '';
    var i;

    for (i = start, length += start; i < length; i++) {
      str += fromCharCode(dataView.getUint8(i));
    }

    return str;
  }

  function getOrientation(arrayBuffer) {
    var dataView = new DataView(arrayBuffer);
    var length = dataView.byteLength;
    var orientation;
    var exifIDCode;
    var tiffOffset;
    var firstIFDOffset;
    var littleEndian;
    var endianness;
    var app1Start;
    var ifdStart;
    var offset;
    var i;

    // Only handle JPEG image (start by 0xFFD8)
    if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
      offset = 2;

      while (offset < length) {
        if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
          app1Start = offset;
          break;
        }

        offset++;
      }
    }

    if (app1Start) {
      exifIDCode = app1Start + 4;
      tiffOffset = app1Start + 10;

      if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
        endianness = dataView.getUint16(tiffOffset);
        littleEndian = endianness === 0x4949;

        if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
          if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
            firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);

            if (firstIFDOffset >= 0x00000008) {
              ifdStart = tiffOffset + firstIFDOffset;
            }
          }
        }
      }
    }

    if (ifdStart) {
      length = dataView.getUint16(ifdStart, littleEndian);

      for (i = 0; i < length; i++) {
        offset = ifdStart + i * 12 + 2;

        if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) {

          // 8 is the offset of the current tag's value
          offset += 8;

          // Get the original orientation value
          orientation = dataView.getUint16(offset, littleEndian);
          break;
        }
      }
    }

    return orientation;
  }

  function dataURLToArrayBuffer(dataURL) {
    var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');
    var binary = atob(base64);
    var length = binary.length;
    var arrayBuffer = new ArrayBuffer(length);
    var dataView = new Uint8Array(arrayBuffer);
    var i;

    for (i = 0; i < length; i++) {
      dataView[i] = binary.charCodeAt(i);
    }

    return arrayBuffer;
  }

  // Only available for JPEG image
  function arrayBufferToDataURL(arrayBuffer) {
    var dataView = new Uint8Array(arrayBuffer);
    var length = dataView.length;
    var base64 = '';
    var i;

    for (i = 0; i < length; i++) {
      base64 += fromCharCode(dataView[i]);
    }

    return 'data:image/jpeg;base64,' + btoa(base64);
  }
<|endoftext|>


<commit_before>/* eslint-disable babel/quotes */

require('dotenv').config()

const convict = require('convict')

module.exports = convict({
  api: {
    endpoint: {
      default: 'http://localhost:4000/graphql',
      env: 'API_ENDPOINT',
      format: 'url',
    },
    endpointSSR: {
      default: 'http://klicker-api:4000/graphql',
      env: 'API_ENDPOINT_SSR',
      format: 'url',
    },
    endpointWS: {
      default: 'ws://localhost:4000/graphql',
      env: 'API_ENDPOINT_WS',
      format: String,
    },
  },
  app: {
    baseUrl: {
      default: 'http://localhost:3000',
      env: 'APP_BASE_URL',
      format: 'url',
    },
    gzip: {
      default: true,
      env: 'APP_GZIP',
      format: Boolean,
    },
    joinUrl: {
      default: undefined,
      env: 'APP_JOIN_URL',
      format: 'url',
    },
    persistQueries: {
      default: false,
      env: 'APP_PERSIST_QUERIES',
      format: Boolean,
    },
    port: {
      default: 3000,
      env: 'APP_PORT',
      format: 'port',
    },
    staticPath: {
      default: 'public',
      env: 'APP_STATIC_PATH',
      format: String,
    },
    trustProxy: {
      default: false,
      env: 'APP_TRUST_PROXY',
      format: Boolean,
    },
  },
  cache: {
    pages: {
      join: {
        default: 30,
        env: 'CACHE_PAGES_JOIN',
        format: 'int',
      },
      landing: {
        default: 600,
        env: 'CACHE_PAGES_LANDING',
        format: 'int',
      },
      qr: {
        default: 300,
        env: 'CACHE_PAGES_QR',
        format: 'int',
      },
    },
    redis: {
      db: {
        default: 0,
        env: 'CACHE_REDIS_DB',
        format: 'nat',
      },
      enabled: {
        default: false,
        env: 'CACHE_REDIS_ENABLED',
        format: Boolean,
      },
      host: {
        default: undefined,
        env: 'CACHE_REDIS_HOST',
        format: String,
      },
      password: {
        default: undefined,
        env: 'CACHE_REDIS_PASSWORD',
        format: String,
        sensitive: true,
      },
      port: {
        default: 6379,
        env: 'CACHE_REDIS_PORT',
        format: 'port',
      },
    },
  },
  env: {
    arg: 'nodeEnv',
    default: 'development',
    env: 'NODE_ENV',
    format: ['production', 'development', 'test'],
  },
  s3: {
    rootUrl: {
      default: undefined,
      env: 'S3_ROOT_URL',
      format: 'url',
    },
  },
  security: {
    csp: {
      connectSrc: {
        default: ["'self'", process.env.API_ENDPOINT, process.env.API_ENDPOINT_WS],
        env: 'SECURITY_CSP_CONNECT_SRC',
        format: Array,
      },
      defaultSrc: {
        default: ["'self'"],
        env: 'SECURITY_CSP_DEFAULT_SRC',
        format: Array,
      },
      enabled: {
        default: false,
        env: 'SECURITY_CSP_ENABLED',
        format: Boolean,
      },
      enforce: {
        default: false,
        env: 'SECURITY_CSP_ENFORCE',
        format: Boolean,
      },
      fontSrc: {
        default: ["'self'", 'fonts.gstatic.com'],
        env: 'SECURITY_CSP_FONT_SRC',
        format: Array,
      },
      imgSrc: {
        default: ["'self'"],
        env: 'SECURITY_CSP_IMG_SRC',
        format: Array,
      },
      reportUri: {
        default: undefined,
        env: 'SECURITY_CSP_REPORT_URI',
        format: 'url',
      },
      scriptSrc: {
        default: ["'self'", "'unsafe-inline'", 'cdn.polyfill.io'],
        env: 'SECURITY_CSP_SCRIPT_SRC',
        format: Array,
      },
      styleSrc: {
        default: [
          "'self'",
          "'unsafe-inline'",
          'maxcdn.bootstrapcdn.com',
          'fonts.googleapis.com',
          'cdnjs.cloudflare.com',
        ],
        env: 'SECURITY_CSP_STYLE_SRC',
        format: Array,
      },
    },
    expectCt: {
      enabled: {
        default: true,
        env: 'SECURITY_EXPECT_CT_ENABLED',
        format: Boolean,
      },
      enforce: {
        default: false,
        env: 'SECURITY_EXPECT_CT_ENFORCE',
        format: Boolean,
      },
      maxAge: {
        default: 0,
        env: 'SECURITY_EXPECT_CT_MAX_AGE',
        format: 'int',
      },
      reportUri: {
        default: undefined,
        env: 'SECURITY_EXPECT_CT_REPORT_URI',
        format: 'url',
      },
    },
    fingerprinting: {
      default: true,
      env: 'SECURITY_FINGERPRINTING',
      format: Boolean,
    },
    frameguard: {
      ancestors: {
        default: ["'none'"],
        env: 'SECURITY_FRAMEGUARD_ANCESTORS',
        format: Array,
      },
      enabled: {
        default: false,
        env: 'SECURITY_FRAMEGUARD_ENABLED',
        format: Boolean,
      },
    },
    hsts: {
      enabled: {
        default: false,
        env: 'SECURITY_HSTS_ENABLED',
        format: Boolean,
      },
      includeSubdomains: {
        default: false,
        env: 'SECURITY_HSTS_INCLUDE_SUBDOMAINS',
        format: Boolean,
      },
      maxAge: {
        default: 0,
        env: 'SECURITY_HSTS_MAX_AGE',
        format: 'nat',
      },
      preload: {
        default: undefined,
        env: 'SECURITY_HSTS_PRELOAD',
        format: Boolean,
      },
    },
    referrerPolicy: {
      default: undefined,
      env: 'SECURITY_REFERRER_POLICY',
      format: String,
    },
  },
  services: {
    // Elastic APM
    apm: {
      enabled: {
        default: false,
        env: 'SERVICES_APM_ENABLED',
        format: Boolean,
      },
      monitorDev: {
        default: false,
        env: 'SERVICES_APM_DEV',
        format: Boolean,
      },
      secretToken: {
        default: undefined,
        env: 'SERVICES_APM_SECRET_TOKEN',
        format: String,
        sensitive: true,
      },
      serverUrl: {
        default: undefined,
        env: 'SERVICES_APM_SERVER_URL',
        format: 'url',
      },
      serviceName: {
        default: 'klicker-react',
        env: 'SERVICES_APM_SERVICE_NAME',
        format: String,
      },
      withRum: {
        default: false,
        env: 'SERVICES_APM_WITH_RUM',
        format: Boolean,
      },
    },
    googleAnalytics: {
      enabled: {
        default: false,
        env: 'SERVICES_GOOGLE_ANALYTICS_ENABLED',
        format: Boolean,
      },
      trackingId: {
        default: undefined,
        env: 'SERVICES_GOOGLE_ANALYTICS_TRACKING_ID',
        format: String,
        sensitive: true,
      },
    },
    logrocket: {
      appId: {
        default: undefined,
        env: 'SERVICES_LOGROCKET_APP_ID',
        format: String,
        sensitive: true,
      },
      enabled: {
        default: false,
        env: 'SERVICES_LOGROCKET_ENABLED',
        format: Boolean,
      },
    },
    sentry: {
      dsn: {
        default: undefined,
        env: 'SERVICES_SENTRY_DSN',
        format: Boolean,
      },
      enabled: {
        default: false,
        env: 'SERVICES_SENTRY_ENABLED',
        format: Boolean,
      },
    },
    slaask: {
      enabled: {
        default: false,
        env: 'SERVICES_SLAASK_ENABLED',
        format: Boolean,
      },
      widgetKey: {
        default: undefined,
        env: 'SERVICES_SLAASK_WIDGET_KEY',
        format: String,
        sensitive: true,
      },
    },
  },
})
<commit_msg>(fix) Ensure that sentry dsn is a string<commit_after>/* eslint-disable babel/quotes */

require('dotenv').config()

const convict = require('convict')

module.exports = convict({
  api: {
    endpoint: {
      default: 'http://localhost:4000/graphql',
      env: 'API_ENDPOINT',
      format: 'url',
    },
    endpointSSR: {
      default: 'http://klicker-api:4000/graphql',
      env: 'API_ENDPOINT_SSR',
      format: 'url',
    },
    endpointWS: {
      default: 'ws://localhost:4000/graphql',
      env: 'API_ENDPOINT_WS',
      format: String,
    },
  },
  app: {
    baseUrl: {
      default: 'http://localhost:3000',
      env: 'APP_BASE_URL',
      format: 'url',
    },
    gzip: {
      default: true,
      env: 'APP_GZIP',
      format: Boolean,
    },
    joinUrl: {
      default: undefined,
      env: 'APP_JOIN_URL',
      format: 'url',
    },
    persistQueries: {
      default: false,
      env: 'APP_PERSIST_QUERIES',
      format: Boolean,
    },
    port: {
      default: 3000,
      env: 'APP_PORT',
      format: 'port',
    },
    staticPath: {
      default: 'public',
      env: 'APP_STATIC_PATH',
      format: String,
    },
    trustProxy: {
      default: false,
      env: 'APP_TRUST_PROXY',
      format: Boolean,
    },
  },
  cache: {
    pages: {
      join: {
        default: 30,
        env: 'CACHE_PAGES_JOIN',
        format: 'int',
      },
      landing: {
        default: 600,
        env: 'CACHE_PAGES_LANDING',
        format: 'int',
      },
      qr: {
        default: 300,
        env: 'CACHE_PAGES_QR',
        format: 'int',
      },
    },
    redis: {
      db: {
        default: 0,
        env: 'CACHE_REDIS_DB',
        format: 'nat',
      },
      enabled: {
        default: false,
        env: 'CACHE_REDIS_ENABLED',
        format: Boolean,
      },
      host: {
        default: undefined,
        env: 'CACHE_REDIS_HOST',
        format: String,
      },
      password: {
        default: undefined,
        env: 'CACHE_REDIS_PASSWORD',
        format: String,
        sensitive: true,
      },
      port: {
        default: 6379,
        env: 'CACHE_REDIS_PORT',
        format: 'port',
      },
    },
  },
  env: {
    arg: 'nodeEnv',
    default: 'development',
    env: 'NODE_ENV',
    format: ['production', 'development', 'test'],
  },
  s3: {
    rootUrl: {
      default: undefined,
      env: 'S3_ROOT_URL',
      format: 'url',
    },
  },
  security: {
    csp: {
      connectSrc: {
        default: ["'self'", process.env.API_ENDPOINT, process.env.API_ENDPOINT_WS],
        env: 'SECURITY_CSP_CONNECT_SRC',
        format: Array,
      },
      defaultSrc: {
        default: ["'self'"],
        env: 'SECURITY_CSP_DEFAULT_SRC',
        format: Array,
      },
      enabled: {
        default: false,
        env: 'SECURITY_CSP_ENABLED',
        format: Boolean,
      },
      enforce: {
        default: false,
        env: 'SECURITY_CSP_ENFORCE',
        format: Boolean,
      },
      fontSrc: {
        default: ["'self'", 'fonts.gstatic.com'],
        env: 'SECURITY_CSP_FONT_SRC',
        format: Array,
      },
      imgSrc: {
        default: ["'self'"],
        env: 'SECURITY_CSP_IMG_SRC',
        format: Array,
      },
      reportUri: {
        default: undefined,
        env: 'SECURITY_CSP_REPORT_URI',
        format: 'url',
      },
      scriptSrc: {
        default: ["'self'", "'unsafe-inline'", 'cdn.polyfill.io'],
        env: 'SECURITY_CSP_SCRIPT_SRC',
        format: Array,
      },
      styleSrc: {
        default: [
          "'self'",
          "'unsafe-inline'",
          'maxcdn.bootstrapcdn.com',
          'fonts.googleapis.com',
          'cdnjs.cloudflare.com',
        ],
        env: 'SECURITY_CSP_STYLE_SRC',
        format: Array,
      },
    },
    expectCt: {
      enabled: {
        default: true,
        env: 'SECURITY_EXPECT_CT_ENABLED',
        format: Boolean,
      },
      enforce: {
        default: false,
        env: 'SECURITY_EXPECT_CT_ENFORCE',
        format: Boolean,
      },
      maxAge: {
        default: 0,
        env: 'SECURITY_EXPECT_CT_MAX_AGE',
        format: 'int',
      },
      reportUri: {
        default: undefined,
        env: 'SECURITY_EXPECT_CT_REPORT_URI',
        format: 'url',
      },
    },
    fingerprinting: {
      default: true,
      env: 'SECURITY_FINGERPRINTING',
      format: Boolean,
    },
    frameguard: {
      ancestors: {
        default: ["'none'"],
        env: 'SECURITY_FRAMEGUARD_ANCESTORS',
        format: Array,
      },
      enabled: {
        default: false,
        env: 'SECURITY_FRAMEGUARD_ENABLED',
        format: Boolean,
      },
    },
    hsts: {
      enabled: {
        default: false,
        env: 'SECURITY_HSTS_ENABLED',
        format: Boolean,
      },
      includeSubdomains: {
        default: false,
        env: 'SECURITY_HSTS_INCLUDE_SUBDOMAINS',
        format: Boolean,
      },
      maxAge: {
        default: 0,
        env: 'SECURITY_HSTS_MAX_AGE',
        format: 'nat',
      },
      preload: {
        default: undefined,
        env: 'SECURITY_HSTS_PRELOAD',
        format: Boolean,
      },
    },
    referrerPolicy: {
      default: undefined,
      env: 'SECURITY_REFERRER_POLICY',
      format: String,
    },
  },
  services: {
    // Elastic APM
    apm: {
      enabled: {
        default: false,
        env: 'SERVICES_APM_ENABLED',
        format: Boolean,
      },
      monitorDev: {
        default: false,
        env: 'SERVICES_APM_DEV',
        format: Boolean,
      },
      secretToken: {
        default: undefined,
        env: 'SERVICES_APM_SECRET_TOKEN',
        format: String,
        sensitive: true,
      },
      serverUrl: {
        default: undefined,
        env: 'SERVICES_APM_SERVER_URL',
        format: 'url',
      },
      serviceName: {
        default: 'klicker-react',
        env: 'SERVICES_APM_SERVICE_NAME',
        format: String,
      },
      withRum: {
        default: false,
        env: 'SERVICES_APM_WITH_RUM',
        format: Boolean,
      },
    },
    googleAnalytics: {
      enabled: {
        default: false,
        env: 'SERVICES_GOOGLE_ANALYTICS_ENABLED',
        format: Boolean,
      },
      trackingId: {
        default: undefined,
        env: 'SERVICES_GOOGLE_ANALYTICS_TRACKING_ID',
        format: String,
        sensitive: true,
      },
    },
    logrocket: {
      appId: {
        default: undefined,
        env: 'SERVICES_LOGROCKET_APP_ID',
        format: String,
        sensitive: true,
      },
      enabled: {
        default: false,
        env: 'SERVICES_LOGROCKET_ENABLED',
        format: Boolean,
      },
    },
    sentry: {
      dsn: {
        default: undefined,
        env: 'SERVICES_SENTRY_DSN',
        format: String,
      },
      enabled: {
        default: false,
        env: 'SERVICES_SENTRY_ENABLED',
        format: Boolean,
      },
    },
    slaask: {
      enabled: {
        default: false,
        env: 'SERVICES_SLAASK_ENABLED',
        format: Boolean,
      },
      widgetKey: {
        default: undefined,
        env: 'SERVICES_SLAASK_WIDGET_KEY',
        format: String,
        sensitive: true,
      },
    },
  },
})
<|endoftext|>


<commit_before>'use strict';
class RenderingContext {
  constructor( id ) {
    const canvas = document.getElementById( id );
    this.canvas = canvas;
    this.gl = canvas.getContext( 'webgl' ) ||
                canvas.getContext( 'experimental-webgl' );
  }

  createProgram( ids ) {
    const gl      = this.gl;
    const program = gl.createProgram();

    ids.forEach( ( id ) => {
      gl.attachShader( program, this.createShader( id ) );
    } );

    gl.linkProgram( program );

    if ( !gl.getProgramParameter( program, gl.LINK_STATUS ) ) {
      console.error( gl.getProgramInfoLog( program ) );
    }

    return program;
  }

  useProgram( program ) {
    this.gl.useProgram( program );
  }

  createShader( id ) {
    const gl     = this.gl;
    const source = document.getElementById( id );
    let shader;

    switch ( source.type ) {
    case 'x-shader/x-vertex':
      shader = gl.createShader( gl.VERTEX_SHADER );
      break;
    case 'x-shader/x-fragment':
      shader = gl.createShader( gl.FRAGMENT_SHADER );
      break;
    default :
      console.error( 'The shader type is not an accepted value.' );
    }
    gl.shaderSource( shader, source.text );
    gl.compileShader( shader );

    if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) {
      console.error( gl.getShaderInfoLog( shader ) );
    }

    return shader;
  }

  bindFramebuffer( frameBuffer ) {
    this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, frameBuffer );
  }

  createFrameBuffer( width, height ) {
    const gl = this.gl;
    const frameBuffer = gl.createFramebuffer();

    gl.bindFramebuffer( gl.FRAMEBUFFER, frameBuffer);

    const renderBuffer = gl.createRenderbuffer();
    gl.bindRenderbuffer( gl.RENDERBUFFER, renderBuffer );

    gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height );
    gl.framebufferRenderbuffer(
      gl.FRAMEBUFFER,
      gl.DEPTH_ATTACHMENT,
      gl.RENDERBUFFER,
      renderBuffer
    );

    const texture = this.createFrameBufferTexture( width, height );
    gl.bindRenderbuffer( gl.RENDERBUFFER, null );
    gl.bindFramebuffer( gl.FRAMEBUFFER, null );

    return {value : frameBuffer, renderbuffer : renderBuffer, texture : texture};
  }

  createFrameBufferTexture( width, height ) {
    const gl = this.gl;
    const texture = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, texture );

    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      width,
      height,
      0,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      null);

    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );

    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );
    gl.framebufferTexture2D(
      gl.FRAMEBUFFER,
      gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D,
      texture,
      0
    );

    gl.bindTexture( gl.TEXTURE_2D, null );

    return texture;
  }

  bindVbos( program, vboAttribs ) {
    vboAttribs.forEach( ( vboAttrib ) => {
      this.bindVbo( program, vboAttrib );
    });
  }

  bindVbo( program, vboAttrib ) {
    const gl       = this.gl;
    const location = gl.getAttribLocation( program, vboAttrib.name );
    gl.bindBuffer( gl.ARRAY_BUFFER, this.createVbo( vboAttrib.value ) );
    gl.enableVertexAttribArray( location );
    gl.vertexAttribPointer( location, vboAttrib.stride, gl.FLOAT, false, 0, 0 );
  }

  createVbo( value ) {
    const gl  = this.gl;
    const vbo = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( value ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ARRAY_BUFFER, null );
    return vbo;
  }

  bindIbo( index ) {
    const gl  = this.gl;
    const ibo = gl.createBuffer();
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
    gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Int16Array( index ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
  }

  createCanvasTexture( canvas2d ) {
    const gl = this.gl;
    const texture = gl.createTexture();

    gl.bindTexture( gl.TEXTURE_2D, texture );
    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      canvas2d
      );
    gl.generateMipmap( gl.TEXTURE_2D );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );

    gl.bindTexture( gl.TEXTURE_2D, null );

    return texture;
  }

  bindTexture( texture, slot ) {
    const gl = this.gl;
    gl.activeTexture( gl.TEXTURE0 + slot );
    gl.bindTexture( gl.TEXTURE_2D, texture );
  }

  enable( cap ) {
    this.gl.enable( cap );
  }

  disable( cap ) {
    this.gl.disable( cap );
  }

  toggleCulFace( enable ) {
    const gl = this.gl;
    if ( enable ) {
      gl.enable( gl.CULL_FACE );
    } else {
      gl.disable( gl.CULL_FACE );
    }
  }

  toggleDepthFunc( enable ) {
    const gl = this.gl;
    if ( enable ) {
      gl.enable( gl.DEPTH_TEST );
    } else {
      gl.disable( gl.DEPTH_TEST );
    }
  }

  depthFunc() {
    const gl = this.gl;
    gl.depthFunc( gl.LEQUAL );
  }

  toggleBlend( enable ) {
    const gl = this.gl;
    if ( enable ) {
      gl.enable( gl.BLEND );
    } else {
      gl.disable( gl.BLEND );
    }
  }

  setBlending( type ) {
    const gl = this.gl;

    switch ( type ) {
    case RenderingContext.AdditiveBlending:
      gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
      break;
    default:
      break;
    }
  }

  static get AdditiveBlending() {
    return 'AdditiveBlending';
  }

  bindUniforms( program, uniformAttribs ) {
    uniformAttribs.forEach( ( uniformAttrib ) => {
      this.bindUniform( program, uniformAttrib );
    });
  }

  bindUniform( program, uniformAttrib ) {
    const gl = this.gl;
    const { name, type, value } = uniformAttrib;
    const location = gl.getUniformLocation( program, name );

    switch ( type ) {
    case 'matrix4fv':
      gl.uniformMatrix4fv( location, false, value );
      break;
    case '4fv':
      gl.uniform4fv( location, value );
      break;
    case '3fv':
      gl.uniform3fv( location, value );
      break;
    case '2fv':
      gl.uniform2fv( location, value );
      break;
    case '1fv':
      gl.uniform1fv( location, value );
      break;
    case '1f':
      gl.uniform1f( location, value );
      break;
    case '1iv':
      gl.uniform1iv( location, value );
      break;
    case '1i':
      gl.uniform1i( location, value );
      break;
    default:
    }
  }

  clear( color, depth ) {
    const gl = this.gl;
    let flag = gl.COLOR_BUFFER_BIT;

    gl.clearColor( color.r, color.g, color.b, color.a );

    if ( depth ) {
      gl.clearDepth( depth );
      flag = flag | gl.DEPTH_BUFFER_BIT;
    }

    gl.clear( flag );
  }

  viewport( viewport ) {
    this.gl.viewport(
      viewport.x,
      viewport.y,
      viewport.width,
      viewport.height);
  }

  drawArrays( mode, count, first = 0 ) {
    const gl = this.gl;
    gl.drawArrays( mode, first, count );
  }

  drawElements( mode, count, offset = 0 ) {
    const gl = this.gl;
    gl.drawElements( mode, count, gl.UNSIGNED_SHORT, offset );
  }
}

export { RenderingContext };
<commit_msg>Fix the code style<commit_after>'use strict';
class RenderingContext {
  constructor( id ) {
    const canvas = document.getElementById( id );
    this.canvas = canvas;
    this.gl = canvas.getContext( 'webgl' ) ||
                canvas.getContext( 'experimental-webgl' );
  }

  createProgram( ids ) {
    const gl      = this.gl;
    const program = gl.createProgram();

    ids.forEach( ( id ) => {
      gl.attachShader( program, this.createShader( id ) );
    } );

    gl.linkProgram( program );

    if ( !gl.getProgramParameter( program, gl.LINK_STATUS ) ) {
      console.error( gl.getProgramInfoLog( program ) );
    }

    return program;
  }

  useProgram( program ) {
    this.gl.useProgram( program );
  }

  createShader( id ) {
    const gl     = this.gl;
    const source = document.getElementById( id );
    let shader;

    switch ( source.type ) {
    case 'x-shader/x-vertex':
      shader = gl.createShader( gl.VERTEX_SHADER );
      break;
    case 'x-shader/x-fragment':
      shader = gl.createShader( gl.FRAGMENT_SHADER );
      break;
    default :
      console.error( 'The shader type is not an accepted value.' );
    }
    gl.shaderSource( shader, source.text );
    gl.compileShader( shader );

    if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) {
      console.error( gl.getShaderInfoLog( shader ) );
    }

    return shader;
  }

  bindFramebuffer( frameBuffer ) {
    this.gl.bindFramebuffer( this.gl.FRAMEBUFFER, frameBuffer );
  }

  createFrameBuffer( width, height ) {
    const gl = this.gl;
    const frameBuffer = gl.createFramebuffer();

    gl.bindFramebuffer( gl.FRAMEBUFFER, frameBuffer);

    const renderBuffer = gl.createRenderbuffer();
    gl.bindRenderbuffer( gl.RENDERBUFFER, renderBuffer );

    gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height );
    gl.framebufferRenderbuffer(
      gl.FRAMEBUFFER,
      gl.DEPTH_ATTACHMENT,
      gl.RENDERBUFFER,
      renderBuffer
    );

    const texture = this.createFrameBufferTexture( width, height );
    gl.bindRenderbuffer( gl.RENDERBUFFER, null );
    gl.bindFramebuffer( gl.FRAMEBUFFER, null );

    return { value : frameBuffer, renderbuffer : renderBuffer, texture : texture };
  }

  createFrameBufferTexture( width, height ) {
    const gl = this.gl;
    const texture = gl.createTexture();
    gl.bindTexture( gl.TEXTURE_2D, texture );

    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      width,
      height,
      0,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      null);

    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );

    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );
    gl.framebufferTexture2D(
      gl.FRAMEBUFFER,
      gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D,
      texture,
      0
    );

    gl.bindTexture( gl.TEXTURE_2D, null );

    return texture;
  }

  bindVbos( program, vboAttribs ) {
    vboAttribs.forEach( ( vboAttrib ) => {
      this.bindVbo( program, vboAttrib );
    });
  }

  bindVbo( program, vboAttrib ) {
    const gl       = this.gl;
    const location = gl.getAttribLocation( program, vboAttrib.name );
    gl.bindBuffer( gl.ARRAY_BUFFER, this.createVbo( vboAttrib.value ) );
    gl.enableVertexAttribArray( location );
    gl.vertexAttribPointer( location, vboAttrib.stride, gl.FLOAT, false, 0, 0 );
  }

  createVbo( value ) {
    const gl  = this.gl;
    const vbo = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( value ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ARRAY_BUFFER, null );
    return vbo;
  }

  bindIbo( index ) {
    const gl  = this.gl;
    const ibo = gl.createBuffer();
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
    gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Int16Array( index ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
  }

  createCanvasTexture( canvas2d ) {
    const gl = this.gl;
    const texture = gl.createTexture();

    gl.bindTexture( gl.TEXTURE_2D, texture );
    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      canvas2d
      );
    gl.generateMipmap( gl.TEXTURE_2D );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );

    gl.bindTexture( gl.TEXTURE_2D, null );

    return texture;
  }

  bindTexture( texture, slot ) {
    const gl = this.gl;
    gl.activeTexture( gl.TEXTURE0 + slot );
    gl.bindTexture( gl.TEXTURE_2D, texture );
  }

  enable( cap ) {
    this.gl.enable( cap );
  }

  disable( cap ) {
    this.gl.disable( cap );
  }

  toggleCulFace( enable ) {
    const gl = this.gl;
    if ( enable ) {
      gl.enable( gl.CULL_FACE );
    } else {
      gl.disable( gl.CULL_FACE );
    }
  }

  toggleDepthFunc( enable ) {
    const gl = this.gl;
    if ( enable ) {
      gl.enable( gl.DEPTH_TEST );
    } else {
      gl.disable( gl.DEPTH_TEST );
    }
  }

  depthFunc() {
    const gl = this.gl;
    gl.depthFunc( gl.LEQUAL );
  }

  toggleBlend( enable ) {
    const gl = this.gl;
    if ( enable ) {
      gl.enable( gl.BLEND );
    } else {
      gl.disable( gl.BLEND );
    }
  }

  setBlending( type ) {
    const gl = this.gl;

    switch ( type ) {
    case RenderingContext.AdditiveBlending:
      gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE );
      break;
    default:
      break;
    }
  }

  static get AdditiveBlending() {
    return 'AdditiveBlending';
  }

  bindUniforms( program, uniformAttribs ) {
    uniformAttribs.forEach( ( uniformAttrib ) => {
      this.bindUniform( program, uniformAttrib );
    });
  }

  bindUniform( program, uniformAttrib ) {
    const gl = this.gl;
    const { name, type, value } = uniformAttrib;
    const location = gl.getUniformLocation( program, name );

    switch ( type ) {
    case 'matrix4fv':
      gl.uniformMatrix4fv( location, false, value );
      break;
    case '4fv':
      gl.uniform4fv( location, value );
      break;
    case '3fv':
      gl.uniform3fv( location, value );
      break;
    case '2fv':
      gl.uniform2fv( location, value );
      break;
    case '1fv':
      gl.uniform1fv( location, value );
      break;
    case '1f':
      gl.uniform1f( location, value );
      break;
    case '1iv':
      gl.uniform1iv( location, value );
      break;
    case '1i':
      gl.uniform1i( location, value );
      break;
    default:
    }
  }

  clear( color, depth ) {
    const gl = this.gl;
    let flag = gl.COLOR_BUFFER_BIT;

    gl.clearColor( color.r, color.g, color.b, color.a );

    if ( depth ) {
      gl.clearDepth( depth );
      flag = flag | gl.DEPTH_BUFFER_BIT;
    }

    gl.clear( flag );
  }

  viewport( viewport ) {
    this.gl.viewport(
      viewport.x,
      viewport.y,
      viewport.width,
      viewport.height);
  }

  drawArrays( mode, count, first = 0 ) {
    const gl = this.gl;
    gl.drawArrays( mode, first, count );
  }

  drawElements( mode, count, offset = 0 ) {
    const gl = this.gl;
    gl.drawElements( mode, count, gl.UNSIGNED_SHORT, offset );
  }
}

export { RenderingContext };
<|endoftext|>


<commit_before>'use strict';
class RenderingContext {
  constructor( canvas ) {
    this.canvas  = canvas;
    this.gl      = canvas.getContext( 'webgl' ) ||
                      canvas.getContext( 'experimental-webgl' );
  }

  createProgram( ids ) {
    let gl      = this.gl;
    let program = gl.createProgram();

    ids.forEach( ( id ) => {
      gl.attachShader( program, this.createShader( id ) );
    } );

    gl.linkProgram( program );

    if ( !gl.getProgramParameter( program, gl.LINK_STATUS ) ) {
      console.error( gl.getProgramInfoLog( program ) );
    }

    return program;
  }

  useProgram( program ) {
    this.gl.useProgram( program );
  }

  createShader( id ) {
    let gl     = this.gl;
    let source = document.getElementById( id );
    let shader;

    switch ( source.type ) {
    case 'x-shader/x-vertex':
      shader = gl.createShader( gl.VERTEX_SHADER );
      break;
    case 'x-shader/x-fragment':
      shader = gl.createShader( gl.FRAGMENT_SHADER );
      break;
    default :
      console.error( 'The shader type is not an accepted value.' );
    }

    gl.shaderSource( shader, source.text );
    gl.compileShader( shader );

    if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) {
      console.error( gl.getShaderInfoLog( shader ) );
    }

    return shader;
  }

  bindVbos( vboAttribs ) {
    vboAttribs.forEach( ( vboAttrib ) => {
      this.bindVbo( vboAttrib.name, vboAttrib.vertices, vboAttrib.stride );
    });
  }

  bindVbo( program, vboAttrib ) {
    let gl       = this.gl;
    let location = gl.getAttribLocation( program, vboAttrib.name );
    gl.bindBuffer( gl.ARRAY_BUFFER, this.createVbo( vboAttrib.value ) );
    gl.enableVertexAttribArray( location );
    gl.vertexAttribPointer( location, vboAttrib.stride, gl.FLOAT, false, 0, 0 );
  }

  createVbo( vertices ) {
    let gl  = this.gl;
    let vbo = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ARRAY_BUFFER, null );
    return vbo;
  }

  bindIbo( indexes ) {
    let gl  = this.gl;
    let ibo = gl.createBuffer();
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
    gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Int16Array( indexes ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
  }

  enable( cap ) {
    this.gl.enable( cap );
  }

  disable( cap ) {
    this.gl.disable( cap );
  }

  depthFunc( type ) {
    this.gl.depthFunc( type );
  }

  bindUniforms( uniformAttribs ) {
    uniformAttribs.forEach( ( uniformAttrib ) =>
                            this.bindUniform( uniformAttrib.name,
                                              uniformAttrib.type,
                                              uniformAttrib.value ) );
  }

  bindUniform( name, type, value ) {
    let gl = this.gl;
    let location = gl.getUniformLocation( this.program, name );

    switch ( type ) {
    case 'matrix4fv':
      gl.uniformMatrix4fv( location, false, value );
      break;
    case '4fv':
      gl.uniform4fv( location, value );
      break;
    case '3fv':
      gl.uniform3fv( location, value );
      break;
    case '2fv':
      gl.uniform2fv( location, value );
      break;
    case '1fv':
      gl.uniform1fv( location, value );
      break;
    case '1f':
      gl.uniform1f( location, value );
      break;
    case '1iv':
      gl.uniform1iv( location, value );
      break;
    case '1i':
      gl.uniform1i( location, value );
      break;
    default:
    }
  }

  clear( color, depth ) {
    let gl = this.gl;
    let flag = gl.COLOR_BUFFER_BIT;

    gl.clearColor( color.r, color.g, color.b, color.a );

    if ( depth ) {
      gl.clearDepth( depth );
      flag = flag | gl.DEPTH_BUFFER_BIT;
    }

    gl.clear( flag );
  }

  viewport( viewport ) {
    this.gl.viewport(
      viewport.x,
      viewport.y,
      viewport.width,
      viewport.height);
  }

  drawArrays( mode, count, first = 0 ) {
    let gl = this.gl;
    gl.drawArrays( mode, first, count );
  }

  drawElements( mode, count, offset = 0 ) {
    let gl = this.gl;
    gl.drawElements( mode, count, gl.UNSIGNED_SHORT, offset );
  }
}

export {RenderingContext};
<commit_msg>:art: Refactor a createVbo method.<commit_after>'use strict';
class RenderingContext {
  constructor( canvas ) {
    this.canvas  = canvas;
    this.gl      = canvas.getContext( 'webgl' ) ||
                      canvas.getContext( 'experimental-webgl' );
  }

  createProgram( ids ) {
    let gl      = this.gl;
    let program = gl.createProgram();

    ids.forEach( ( id ) => {
      gl.attachShader( program, this.createShader( id ) );
    } );

    gl.linkProgram( program );

    if ( !gl.getProgramParameter( program, gl.LINK_STATUS ) ) {
      console.error( gl.getProgramInfoLog( program ) );
    }

    return program;
  }

  useProgram( program ) {
    this.gl.useProgram( program );
  }

  createShader( id ) {
    let gl     = this.gl;
    let source = document.getElementById( id );
    let shader;

    switch ( source.type ) {
    case 'x-shader/x-vertex':
      shader = gl.createShader( gl.VERTEX_SHADER );
      break;
    case 'x-shader/x-fragment':
      shader = gl.createShader( gl.FRAGMENT_SHADER );
      break;
    default :
      console.error( 'The shader type is not an accepted value.' );
    }

    gl.shaderSource( shader, source.text );
    gl.compileShader( shader );

    if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) {
      console.error( gl.getShaderInfoLog( shader ) );
    }

    return shader;
  }

  bindVbos( vboAttribs ) {
    vboAttribs.forEach( ( vboAttrib ) => {
      this.bindVbo( vboAttrib.name, vboAttrib.vertices, vboAttrib.stride );
    });
  }

  bindVbo( program, vboAttrib ) {
    let gl       = this.gl;
    let location = gl.getAttribLocation( program, vboAttrib.name );
    gl.bindBuffer( gl.ARRAY_BUFFER, this.createVbo( vboAttrib.value ) );
    gl.enableVertexAttribArray( location );
    gl.vertexAttribPointer( location, vboAttrib.stride, gl.FLOAT, false, 0, 0 );
  }

  createVbo( value ) {
    let gl  = this.gl;
    let vbo = gl.createBuffer();
    gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
    gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( value ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ARRAY_BUFFER, null );
    return vbo;
  }

  bindIbo( indexes ) {
    let gl  = this.gl;
    let ibo = gl.createBuffer();
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
    gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, new Int16Array( indexes ), gl.STATIC_DRAW );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
    gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, ibo );
  }

  enable( cap ) {
    this.gl.enable( cap );
  }

  disable( cap ) {
    this.gl.disable( cap );
  }

  depthFunc( type ) {
    this.gl.depthFunc( type );
  }

  bindUniforms( uniformAttribs ) {
    uniformAttribs.forEach( ( uniformAttrib ) =>
                            this.bindUniform( uniformAttrib.name,
                                              uniformAttrib.type,
                                              uniformAttrib.value ) );
  }

  bindUniform( name, type, value ) {
    let gl = this.gl;
    let location = gl.getUniformLocation( this.program, name );

    switch ( type ) {
    case 'matrix4fv':
      gl.uniformMatrix4fv( location, false, value );
      break;
    case '4fv':
      gl.uniform4fv( location, value );
      break;
    case '3fv':
      gl.uniform3fv( location, value );
      break;
    case '2fv':
      gl.uniform2fv( location, value );
      break;
    case '1fv':
      gl.uniform1fv( location, value );
      break;
    case '1f':
      gl.uniform1f( location, value );
      break;
    case '1iv':
      gl.uniform1iv( location, value );
      break;
    case '1i':
      gl.uniform1i( location, value );
      break;
    default:
    }
  }

  clear( color, depth ) {
    let gl = this.gl;
    let flag = gl.COLOR_BUFFER_BIT;

    gl.clearColor( color.r, color.g, color.b, color.a );

    if ( depth ) {
      gl.clearDepth( depth );
      flag = flag | gl.DEPTH_BUFFER_BIT;
    }

    gl.clear( flag );
  }

  viewport( viewport ) {
    this.gl.viewport(
      viewport.x,
      viewport.y,
      viewport.width,
      viewport.height);
  }

  drawArrays( mode, count, first = 0 ) {
    let gl = this.gl;
    gl.drawArrays( mode, first, count );
  }

  drawElements( mode, count, offset = 0 ) {
    let gl = this.gl;
    gl.drawElements( mode, count, gl.UNSIGNED_SHORT, offset );
  }
}

export {RenderingContext};
<|endoftext|>