<commit_before>(function(window) {

var _createXhr;
if (window.XMLHttpRequest) _createXhr = function(){
    return new window.XMLHttpRequest();
}
else
if (window.ActiveXObject) _createXhr = function(){
    return new window.ActiveXObject("MSXML2.XMLHTTP.3.0");
}

var Pham;

Pham = function(options) {
  this.options = options || {
    url: "../../../../plugin/data-access/api/datasource/analysis/catalog"
  };
};

Pham.prototype = {
  request: function(options) {
    var me = this,
        xhr = _createXhr(),
        url = options.url
    ;
    var method = options.method || "GET";
    xhr.open(method, url, true);
    if (options.headers) {
      var header;
      for (header in options.headers){
        xhr.setRequestHeader(header, options.headers[header]);
      }
    }
    xhr.onreadystatechange = function() {
      var scope = options.scope ? options.scope : window;
      switch (xhr.readyState) {
        case 0:
          if (typeof(options.aborted) === "function") {
            options.aborted.call(scope, me, options);
          }
          break;
        case 4:
          var errorText = null;
          switch (xhr.status) {
            case 200:
              if (typeof(options.success) === "function") {
                var data;
                try {
                  switch (xhr.getResponseHeader("Content-Type")) {
                    case "application/xml":
                    case "text/xml":
                      data = parseXmlText(xhr.responseText);
                      break
                    case "application/json":
                      data = JSON.parse(xhr.responseText);
                      break
                    default:
                      data = xhr.responseText;
                  }
                  options.success.call(scope, me, options, data);
                  break;
                }
                catch (e) {
                  errorText = e.toString();
                }
              }
            default:
              if (typeof(options.failure) === "function") {
                options.failure.call(
                  scope, me, options, status,
                  errorText ? errorText : xhr.statusText
                );
              }
              break;
          }
          break;
      }
    };
    xhr.send(options.data ? options.data : null);
  },
  getDataSourceInfo: function(options){
    var oldSuccess = options.success;
    var scope = options.scope || null;
    options.method = "GET";
    options.headers = {
      "Accept": "text/plain"
    };
    options.success = function(xhr, options, data){
      var doc = {};
      var i, items = data.split(";"), n = items.length, item, value;
      for (i = 0; i < n; i++) {
        item = items[i];
        item = item.split("=");
        value = item[1];
        if (value.length >= 2 &&
          (value.charAt(0) === "\"" && value.charAt(value.length-1) === "\"")
        ||(value.charAt(0) === "'" && value.charAt(value.length-1) === "'")
        ) {
          value = value.substr(1, value.length-2);
        }
        doc[item[0]] = value;
      }
      if (oldSuccess) {
        oldSuccess.call(scope, doc);
      }
    }
    var path = this.options.url.split("/");
    path.pop();
    path.pop();
    options.url = path.join("/") + "/" + options.modelName + "/getAnalysisDatasourceInfo";
    this.request(options);
  },
  getModels: function(options){
    var oldSuccess = options.success;
    var scope = options.scope || null;
    options.method = "GET";
    options.headers = {
      "Accept": "application/xml"
    };
    options.success = function(xhr, options, doc){
      var models = [], items = doc.childNodes[1].childNodes, n = items.length, i, item;
      for (i = 0; i < n; i++){
        item = items[i];
        models[i] = item.childNodes[0].data;
      }
      if (oldSuccess) oldSuccess.call(scope, models);
    }
    options.url = this.options.url;
    this.request(options);
  },
  getModel: function(options){
    var oldSuccess = options.success;
    var scope = options.scope || null;
    options.method = "GET";
    options.headers = {
      "Accept": "application/xml"
    };
    options.success = function(xhr, options, doc){
      model = new MondrianModel(doc);
      model.setName(options.modelName);
      if (oldSuccess) oldSuccess.call(scope, model);
    }
    options.url = this.options.url + "/" + options.modelName;
    this.request(options);
  },
  deleteModel: function(options){
    var scope = options.scope || null;
    options.method = "DELETE";
    options.url = this.options.url + "/" + options.modelName;
    this.request(options);
  },
  postModel: function(options){
    var scope = options.scope || null;
    options.method = "POST";

    options.headers = {
      "Accept": "text/plain"
    };

    var url = this.options.url.split("/");
    url.pop();
    url.pop();
    url.pop();
    url.push("mondrian");
    url.push("postAnalysis");
    options.url = url.join("/");

    var xml = "", model = options.model;
    if (model instanceof MondrianModel) {
      xml = model.toXml();
      xml = xml.substr(xml.indexOf("?>") + 2);
      if (!options.datasource) {
        options.datasource = model.getDataSourceName();
      }
      if (!options.EnableXmla){
        options.EnableXmla = String(model.getXmlaEnabled());
      }
    }
    else
    if (typeof(model) === "string") {
      xml = model;
    }

    var boundary = '---------------------------';
    boundary += Math.floor(Math.random()*32768);
    boundary += Math.floor(Math.random()*32768);
    boundary += Math.floor(Math.random()*32768);

    options.headers = {
      "Content-Type": "multipart/form-data; boundary=" + boundary
    };
    var msg = "--" + boundary +
              "\r\nContent-Disposition: form-data; name=\"uploadAnalysis\"; filename=\"file.xml\"" +
              "\r\nContent-Type: text/xml" +
              "\r\n\r\n" + xml +
              "\r\n--" + boundary +
              "\r\nContent-Disposition: form-data; name=\"parameters\"" +
              "\r\n\r\nDataSource="       + options.datasource +
                      ";overwrite="       + String(iDef(options.overwrite) ?  options.overwrite : false) +
                      ";EnableXmla=" + String(iDef(options.EnableXmla) ?  options.EnableXmla : false) +
              "\r\n--" + boundary + "--";

    options.data = msg;
    var oldSuccess = options.success;
    options.success = function(xhr, options, data){
      if (data === "3") {
        oldSuccess.call(scope, xhr, options, "Success");
      }
      else {
        //check org.pentaho.platform.plugin.services.importer.PlatformImportException
        var error = "";
        switch (data) {
          case "1":   //PUBLISH_TO_SERVER_FAILED
            error = "PUBLISH_TO_SERVER_FAILED";
            break;
          case "2":   //PUBLISH_GENERAL_ERROR
            error = "PUBLISH_GENERAL_ERROR";
            break;
          case "6":   //PUBLISH_DATASOURCE_ERROR
            error = "PUBLISH_DATASOURCE_ERROR";
            break;
          case "5":   //PUBLISH_USERNAME_PASSWORD_FAIL
            error = "PUBLISH_USERNAME_PASSWORD_FAIL";
            break;
          case "7":   //PUBLISH_XMLA_CATALOG_EXISTS
            error = "PUBLISH_XMLA_CATALOG_EXISTS";
            break;
          case "8":   //PUBLISH_SCHEMA_EXISTS_ERROR
            error = "PUBLISH_SCHEMA_EXISTS_ERROR";
            break;
          case "9":   //PUBLISH_CONTENT_EXISTS_ERROR
            error = "PUBLISH_CONTENT_EXISTS_ERROR";
            break;
          case "10":  //PUBLISH_PROHIBITED_SYMBOLS_ERROR;
            error = "PUBLISH_PROHIBITED_SYMBOLS_ERROR";
            break;
        }
        if (options.failure) {
          options.failure.call(scope, xhr, options, 200, error);
        }
      }
    }
    this.request(options);
  },
};

if (typeof(define)==="function" && define.amd) {
  define(function (){
      return Pham;
  });
}
else window.Pham = Pham;

return Pham;
})(typeof exports === "undefined" ? window : exports);
<commit_msg>Modify the service layer api so it is backwards compatible with 5.0.1. This probably means I'm using service calls that will eventually be deprecated. Would be nice to solve this problem generically. We might do that some day.<commit_after>(function(window) {

var _createXhr;
if (window.XMLHttpRequest) _createXhr = function(){
    return new window.XMLHttpRequest();
}
else
if (window.ActiveXObject) _createXhr = function(){
    return new window.ActiveXObject("MSXML2.XMLHTTP.3.0");
}

var Pham;

Pham = function(options) {
  this.options = options || {
    url: "../../../../plugin/data-access/api/datasource/analysis"
  };
};

Pham.prototype = {
  request: function(options) {
    var me = this,
        xhr = _createXhr(),
        url = options.url
    ;
    var method = options.method || "GET";
    xhr.open(method, url, true);
    if (options.headers) {
      var header;
      for (header in options.headers){
        xhr.setRequestHeader(header, options.headers[header]);
      }
    }
    xhr.onreadystatechange = function() {
      var scope = options.scope ? options.scope : window;
      switch (xhr.readyState) {
        case 0:
          if (typeof(options.aborted) === "function") {
            options.aborted.call(scope, me, options);
          }
          break;
        case 4:
          var errorText = null;
          switch (xhr.status) {
            case 200:
              if (typeof(options.success) === "function") {
                var data;
                try {
                  switch (xhr.getResponseHeader("Content-Type")) {
                    case "application/xml":
                    case "text/xml":
                      data = parseXmlText(xhr.responseText);
                      break
                    case "application/json":
                      data = JSON.parse(xhr.responseText);
                      break
                    default:
                      data = xhr.responseText;
                  }
                  options.success.call(scope, me, options, data);
                  break;
                }
                catch (e) {
                  errorText = e.toString();
                }
              }
            default:
              if (typeof(options.failure) === "function") {
                options.failure.call(
                  scope, me, options, status,
                  errorText ? errorText : xhr.statusText
                );
              }
              break;
          }
          break;
      }
    };
    xhr.send(options.data ? options.data : null);
  },
  getDataSourceInfo: function(options){
    var oldSuccess = options.success;
    var scope = options.scope || null;
    options.method = "GET";
    options.headers = {
      "Accept": "text/plain"
    };
    options.success = function(xhr, options, data){
      var doc = {};
      var i, items = data.split(";"), n = items.length, item, value;
      for (i = 0; i < n; i++) {
        item = items[i];
        item = item.split("=");
        value = item[1];
        if (value.length >= 2 &&
          (value.charAt(0) === "\"" && value.charAt(value.length-1) === "\"")
        ||(value.charAt(0) === "'" && value.charAt(value.length-1) === "'")
        ) {
          value = value.substr(1, value.length-2);
        }
        doc[item[0]] = value;
      }
      if (oldSuccess) {
        oldSuccess.call(scope, doc);
      }
    }
    var path = this.options.url.split("/");
    path.pop();
    options.url = path.join("/") + "/" + options.modelName + "/getAnalysisDatasourceInfo";
    this.request(options);
  },
  getModels: function(options){
    var oldSuccess = options.success;
    var scope = options.scope || null;
    options.method = "GET";
    options.headers = {
      "Accept": "application/xml"
    };
    options.success = function(xhr, options, doc){
      var models = [], items = doc.childNodes[1].childNodes, n = items.length, i, item;
      for (i = 0; i < n; i++){
        item = items[i];
        models[i] = item.childNodes[0].data;
      }
      if (oldSuccess) oldSuccess.call(scope, models);
    }
    options.url = this.options.url + "/ids";
    this.request(options);
  },
  getModel: function(options){
    var oldSuccess = options.success;
    var scope = options.scope || null;
    options.method = "GET";
    options.headers = {
      "Accept": "application/xml"
    };
    options.success = function(xhr, options, doc){
      model = new MondrianModel(doc);
      model.setName(options.modelName);
      if (oldSuccess) oldSuccess.call(scope, model);
    }
    options.url = this.options.url + "/" + options.modelName + "/download";
    this.request(options);
  },
  deleteModel: function(options){
    var scope = options.scope || null;
    options.method = "DELETE";
    options.url = this.options.url + "/catalog/" + options.modelName;
    this.request(options);
  },
  postModel: function(options){
    var scope = options.scope || null;
    options.method = "POST";

    options.headers = {
      "Accept": "text/plain"
    };

    var url = this.options.url.split("/");
    url.pop();
    url.pop();
    url.push("mondrian");
    url.push("postAnalysis");
    options.url = url.join("/");

    var xml = "", model = options.model;
    if (model instanceof MondrianModel) {
      xml = model.toXml();
      xml = xml.substr(xml.indexOf("?>") + 2);
      if (!options.datasource) {
        options.datasource = model.getDataSourceName();
      }
      if (!options.EnableXmla){
        options.EnableXmla = String(model.getXmlaEnabled());
      }
    }
    else
    if (typeof(model) === "string") {
      xml = model;
    }

    var boundary = '---------------------------';
    boundary += Math.floor(Math.random()*32768);
    boundary += Math.floor(Math.random()*32768);
    boundary += Math.floor(Math.random()*32768);

    options.headers = {
      "Content-Type": "multipart/form-data; boundary=" + boundary
    };
    var msg = "--" + boundary +
              "\r\nContent-Disposition: form-data; name=\"uploadAnalysis\"; filename=\"file.xml\"" +
              "\r\nContent-Type: text/xml" +
              "\r\n\r\n" + xml +
              "\r\n--" + boundary +
              "\r\nContent-Disposition: form-data; name=\"parameters\"" +
              "\r\n\r\nDataSource="       + options.datasource +
                      ";overwrite="       + String(iDef(options.overwrite) ?  options.overwrite : false) +
                      ";EnableXmla=" + String(iDef(options.EnableXmla) ?  options.EnableXmla : false) +
              "\r\n--" + boundary + "--";

    options.data = msg;
    var oldSuccess = options.success;
    options.success = function(xhr, options, data){
      if (data === "3") {
        oldSuccess.call(scope, xhr, options, "Success");
      }
      else {
        //check org.pentaho.platform.plugin.services.importer.PlatformImportException
        var error = "";
        switch (data) {
          case "1":   //PUBLISH_TO_SERVER_FAILED
            error = "PUBLISH_TO_SERVER_FAILED";
            break;
          case "2":   //PUBLISH_GENERAL_ERROR
            error = "PUBLISH_GENERAL_ERROR";
            break;
          case "6":   //PUBLISH_DATASOURCE_ERROR
            error = "PUBLISH_DATASOURCE_ERROR";
            break;
          case "5":   //PUBLISH_USERNAME_PASSWORD_FAIL
            error = "PUBLISH_USERNAME_PASSWORD_FAIL";
            break;
          case "7":   //PUBLISH_XMLA_CATALOG_EXISTS
            error = "PUBLISH_XMLA_CATALOG_EXISTS";
            break;
          case "8":   //PUBLISH_SCHEMA_EXISTS_ERROR
            error = "PUBLISH_SCHEMA_EXISTS_ERROR";
            break;
          case "9":   //PUBLISH_CONTENT_EXISTS_ERROR
            error = "PUBLISH_CONTENT_EXISTS_ERROR";
            break;
          case "10":  //PUBLISH_PROHIBITED_SYMBOLS_ERROR;
            error = "PUBLISH_PROHIBITED_SYMBOLS_ERROR";
            break;
        }
        if (options.failure) {
          options.failure.call(scope, xhr, options, 200, error);
        }
      }
    }
    this.request(options);
  },
};

if (typeof(define)==="function" && define.amd) {
  define(function (){
      return Pham;
  });
}
else window.Pham = Pham;

return Pham;
})(typeof exports === "undefined" ? window : exports);
<|endoftext|>


<commit_before>(function( $ ) {
  var browser = {}
  browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
  browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
  browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
  browser.msie = /msie/.test(navigator.userAgent.toLowerCase());

  var defaults = {
    max: 10,
    partial: 6,
    hintText: 'Click to reveal completely'
  }

  var alertShown = false>>>>>>> Stashed changes

  $.fn.spoilerAlert = function(opts) {
    var maxBlur = opts.max
    var partialBlur = opts.partial
    var hintText = opts.hintText
    opts = $.extend(defaults, opts || {})
    console.log(opts.max)
    if (!alertShown && browser.msie) {
      alert("WARNING, this site contains spoilers!")
      alertShown = true
    }
    return this.each(function() {
      var $spoiler = $(this)
      $spoiler.data('spoiler-state', 'shrouded')

      var animationTimer = null
      var currentBlur = maxBlur

      var cancelTimer = function() {
        if (animationTimer) {
          clearTimeout(animationTimer)
          animationTimer = null
        }
      }

      var applyBlur = function(radius) {
        currentBlur = radius
        if (browser.msie) {
          // do nothing
        } else if (browser.mozilla) {
          var filterValue = radius > 0 ? "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='blur'><feGaussianBlur stdDeviation='" + radius + "' /></filter></svg>#blur\")" : ''
          $spoiler.css('filter', filterValue)
        } else {
          var filterValue = radius > 0 ? 'blur('+radius+'px)' : ''
          $spoiler.css('filter', filterValue)
          $spoiler.css('-webkit-filter', filterValue)
          $spoiler.css('-moz-filter', filterValue)
          $spoiler.css('-o-filter', filterValue)
          $spoiler.css('-ms-filter', filterValue)
        }
      }

      var performBlur = function(targetBlur, direction) {
        cancelTimer()
        if (currentBlur != targetBlur) {
          applyBlur(currentBlur + direction)
          animationTimer = setTimeout(function() { performBlur(targetBlur, direction) }, 10)
        }
      }

      applyBlur(currentBlur)

      $(this).on('mouseover', function(e) {
        $spoiler.attr('title', hintText)
        if ($spoiler.data('spoiler-state') == 'shrouded') performBlur(partialBlur, -1)
      })
      $(this).on('mouseout', function(e) {
        if ($spoiler.data('spoiler-state') == 'shrouded') performBlur(maxBlur, 1)
      })
      $(this).on('click', function(e) {
        $spoiler.data('spoiler-state', $spoiler.data('spoiler-state') == 'shrouded' ? 'revealed' : 'shrouded')
        $spoiler.attr('title', 'spoiler-state' == 'shrouded' ? hintText : '')
        $spoiler.data('spoiler-state') == 'shrouded' ? performBlur(partialBlur, 1) : performBlur(0, -1)
      })
    })

  };
})( jQuery );
<commit_msg>bad merge<commit_after>(function( $ ) {
  var browser = {}
  browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
  browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
  browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
  browser.msie = /msie/.test(navigator.userAgent.toLowerCase());

  var defaults = {
    max: 10,
    partial: 6,
    hintText: 'Click to reveal completely'
  }

  var alertShown = false

  $.fn.spoilerAlert = function(opts) {
    opts = $.extend(defaults, opts || {})
    var maxBlur = opts.max
    var partialBlur = opts.partial
    var hintText = opts.hintText
    console.log(opts.max)
    if (!alertShown && browser.msie) {
      alert("WARNING, this site contains spoilers!")
      alertShown = true
    }
    return this.each(function() {
      var $spoiler = $(this)
      $spoiler.data('spoiler-state', 'shrouded')

      var animationTimer = null
      var currentBlur = maxBlur

      var cancelTimer = function() {
        if (animationTimer) {
          clearTimeout(animationTimer)
          animationTimer = null
        }
      }

      var applyBlur = function(radius) {
        currentBlur = radius
        if (browser.msie) {
          // do nothing
        } else if (browser.mozilla) {
          var filterValue = radius > 0 ? "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='blur'><feGaussianBlur stdDeviation='" + radius + "' /></filter></svg>#blur\")" : ''
          $spoiler.css('filter', filterValue)
        } else {
          var filterValue = radius > 0 ? 'blur('+radius+'px)' : ''
          $spoiler.css('filter', filterValue)
          $spoiler.css('-webkit-filter', filterValue)
          $spoiler.css('-moz-filter', filterValue)
          $spoiler.css('-o-filter', filterValue)
          $spoiler.css('-ms-filter', filterValue)
        }
      }

      var performBlur = function(targetBlur, direction) {
        cancelTimer()
        if (currentBlur != targetBlur) {
          applyBlur(currentBlur + direction)
          animationTimer = setTimeout(function() { performBlur(targetBlur, direction) }, 10)
        }
      }

      applyBlur(currentBlur)

      $(this).on('mouseover', function(e) {
        $spoiler.attr('title', hintText)
        if ($spoiler.data('spoiler-state') == 'shrouded') performBlur(partialBlur, -1)
      })
      $(this).on('mouseout', function(e) {
        if ($spoiler.data('spoiler-state') == 'shrouded') performBlur(maxBlur, 1)
      })
      $(this).on('click', function(e) {
        $spoiler.data('spoiler-state', $spoiler.data('spoiler-state') == 'shrouded' ? 'revealed' : 'shrouded')
        $spoiler.attr('title', 'spoiler-state' == 'shrouded' ? hintText : '')
        $spoiler.data('spoiler-state') == 'shrouded' ? performBlur(partialBlur, 1) : performBlur(0, -1)
      })
    })

  };
})( jQuery );
<|endoftext|>


<commit_before>
;(function(root, factory) {
    'use strict';

    root.asimov = root.asimov || {};

    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], function(jQuery) {
            root.asimov.core = factory(jQuery);
            return root.asimov.core;
        });
    } else {
        // Browser globals
        root.asimov.core = factory(root.jQuery);
    }
}(this, function($, undefined) {
    'use strict';

    return {
        getElementData: function($elem, prefix) {
            var data = {},

                // does it start with our prefix?
                re = new RegExp('^' + prefix + '[A-Z]'),

                // $.data() turns data-prefix-foo-bar into
                // prefixFooBar, we want it to be prefix-foo-bar
                upperToHyphenLower = function(match) {
                    return '-' + match.toLowerCase();
                };

            $.each($elem.data(), function(key, value) {
                if (re.test(key)) {
                    data[key.replace(/[A-Z]/g, upperToHyphenLower)] = value;
                }
            });

            return data;
        },

        mergeElementData: function($elem, prefix, defaults) {
            // Get an object of dom data attributes that we care about
            var domData = this.getElementData($elem, prefix),
                data = $.extend(true, {}, defaults);

            // Deep merges dom data with the defaults.
            //
            // Transforms hyphen-separated dom data keys into nested
            // objects so they can be deep merged with $.extend.
            //
            // We only merge keys that exist in the defaults object,
            // new keys are never created.
            function recur(root, attrKey, value) {
                var item, i, l;

                for (i = 0, l = attrKey.length; i < l; i += 1) {
                    item = attrKey[i];
                    if ($.isPlainObject(root[item])) {
                        root[item] = $.extend(
                            true, {}, root[item],
                            recur(root[item], attrKey.slice(i + 1), value)
                        );
                    } else if (root[item] !== undefined) {
                        root[item] = value;
                    }
                }

                return root;
            }

            $.each(domData, function(key, value) {
                data = $.extend(
                    true, {}, data,
                    recur(data, key.split(/-/), value)
                );
            });

            return data;
        }
    };
}));
<commit_msg>refactor(js): make getElementData private<commit_after>
;(function(root, factory) {
    'use strict';

    root.asimov = root.asimov || {};

    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], function(jQuery) {
            root.asimov.core = factory(jQuery);
            return root.asimov.core;
        });
    } else {
        // Browser globals
        root.asimov.core = factory(root.jQuery);
    }
}(this, function($, undefined) {
    'use strict';

    var getElementData = function($elem, prefix) {
        var data = {},

            // does it start with our prefix?
            re = new RegExp('^' + prefix + '[A-Z]'),

            // $.data() turns data-prefix-foo-bar into
            // prefixFooBar, we want it to be prefix-foo-bar
            upperToHyphenLower = function(match) {
                return '-' + match.toLowerCase();
            };

        $.each($elem.data(), function(key, value) {
            if (re.test(key)) {
                data[key.replace(/[A-Z]/g, upperToHyphenLower)] = value;
            }
        });

        return data;
    };

    return {
        mergeElementData: function($elem, prefix, defaults) {

            // Get an object of dom data attributes that we care about
            var domData = getElementData($elem, prefix),
                data = $.extend(true, {}, defaults);

            // Deep merges dom data with the defaults.
            //
            // Transforms hyphen-separated dom data keys into nested
            // objects so they can be deep merged with $.extend.
            //
            // We only merge keys that exist in the defaults object,
            // new keys are never created.
            function recur(root, attrKey, value) {
                var item, i, l;

                for (i = 0, l = attrKey.length; i < l; i += 1) {
                    item = attrKey[i];
                    if ($.isPlainObject(root[item])) {
                        root[item] = $.extend(
                            true, {}, root[item],
                            recur(root[item], attrKey.slice(i + 1), value)
                        );
                    } else if (root[item] !== undefined) {
                        root[item] = value;
                    }
                }

                return root;
            }

            $.each(domData, function(key, value) {
                data = $.extend(
                    true, {}, data,
                    recur(data, key.split(/-/), value)
                );
            });

            return data;
        }
    };
}));
<|endoftext|>


<commit_before>'use strict';

Darwinator.GameState = function() {
  this.player   = null;
  this.enemies    = null;
  this.cursors  = null;
  this.map      = null;
  this.tileset  = null;
  this.layer    = null;
  this.fps      = null;
  this.stats    = null;
  this.health   = null;
  this.spawnPositions = [];
  this.numberOfEnemies = 20;
}

Darwinator.GameState.prototype = {

  create: function () {
    this.loadLevel();
    this.game.world.setBounds(0,0, this.map.widthInPixels, this.map.heightInPixels);

    this.cursors = this.game.input.keyboard.createCursorKeys();

    this.player = new Darwinator.Player(this.game, 160, 620, this.cursors, 100, 5, 5);
    this.player.scale.setTo(2,2);

    this.initSpawnPosition();
    this.spawnEnemies();

    this.game.add.existing(this.player);
    this.game.camera.follow(this.player);

    // For development only
    this.fps = this.game.add.text(16, 16, 'FPS: 0', { fontSize: '16px', fill: '#F08' });
    this.fps.fixedToCamera = true;

    this.stats = this.game.add.text(16, 40, '', { fontSize: '16px', fill: '#F08' });
    this.stats.fixedToCamera = true;

    this.health = this.game.add.text(16, 64, '', {fontSize: '16px', fill: '#F08' });
    this.health.fixedToCamera = true;

    this.gameOver = this.game.add.text(this.game.width / 2, this.game.height / 2, '', {fontSize: '48px', fill:'#F08'});
    this.gameOver.fixedToCamera = true;

    Darwinator.Pathfinder = new EasyStar.js();
    Darwinator.Pathfinder.enableDiagonals();
    var indexes = Darwinator.Helpers.convertTileMap(this.map.layers[0].data);
    Darwinator.Pathfinder.setGrid(indexes);
    Darwinator.Pathfinder.setAcceptableTiles([1337, 168, 156, 157, 158, 172, 173, 174, 188, 189, 190, 205]);

    var x = this.game.width / 2
    , y = this.game.height / 2;
    this.pauseText = this.game.add.text(x, y, 'Game paused', { fontSize: '16px', fill: '#fff', align: 'center' });
    this.pauseText.anchor.setTo(0.5, 0.5);
    this.pauseText.fixedToCamera = true;
    this.pauseText.renderable = false;
    this.pauseText.visible = false;
  },

  loadLevel: function() {
    this.map = this.game.add.tilemap('level1');
    this.map.addTilesetImage('tiles', 'tiles');

    Darwinator.setTileSize(this.map.tileWidth, this.map.tileHeight);

    this.map.setCollisionByExclusion([1337, 168, 156, 157, 158, 172, 173, 174, 188, 189, 190, 205]);
    this.map.createLayer('Tile Layer 2');
    this.layer = this.map.createLayer('Tile Layer 1');
    this.layer.debug = true;

    this.map.collisionLayer = this.layer;
    this.layer.resizeWorld();
  },

  spawnEnemies: function () {
    var spawnIndexes = new Array(this.spawnPositions.length);

    for (var i = 0; i < spawnIndexes.length; i++) {
      spawnIndexes[i] = i;
    }

    this.enemies = this.game.add.group();
    var rInd;
    var pos;
    while (this.numberOfEnemies-- && spawnIndexes.length) {
      rInd = Math.round(Math.random() * spawnIndexes.length -1);
      pos = spawnIndexes.splice(rInd,1);
      this.enemies.add(new Darwinator.Enemy(this.game, this.player,
        this.spawnPositions[pos][0],
        this.spawnPositions[pos][1], 100));
    }

    console.log("duurp");
  },

  initSpawnPosition: function () {
    var matrix = Darwinator.Helpers.convertTileMap(this.map.layers[0].data);

    for (var i = 0; i < matrix.length; i++) {
      for(var j = 0; j < matrix[i].length; j++) {
        if (matrix[i][j] === 168){
          this.spawnPositions.push(Darwinator.Helpers.tileToPixels(j,i));
        }
      }
    }
  },

  update: function () {
    // TODO: Move this to the nonexistent resume callback
    if (this.pauseText.visible) this.pauseText.visible = false;

    this.game.physics.collide(this.player, this.layer);
    this.game.physics.collide(this.enemies, this.layer);
    this.game.physics.collide(this.enemies, this.enemies);

    // For development only
    this.fps.content = 'FPS: ' + this.game.time.fps;
    this.stats.content = 'Player stamina: ' + Math.round(this.player.currBreath) + '/' + this.player.stamina;
    this.health.content = 'Health: ' + this.player.health;
  },

  paused: function () {
    this.pauseText.visible = true;
  }

};
<commit_msg>spawns enemies according to tiles<commit_after>'use strict';

Darwinator.GameState = function() {
  this.player   = null;
  this.enemies  = null;
  this.cursors  = null;
  this.map      = null;
  this.tileset  = null;
  this.layer    = null;
  this.fps      = null;
  this.stats    = null;
  this.health   = null;
  this.pauseText = null;
  this.spawnPositions = [];
  this.numberOfEnemies = 10;
}

Darwinator.GameState.prototype = {

  create: function () {
    this.loadLevel();
    this.game.world.setBounds(0,0, this.map.widthInPixels, this.map.heightInPixels);

    this.cursors = this.game.input.keyboard.createCursorKeys();

    this.player = new Darwinator.Player(this.game, 160, 620, this.cursors, 100, 5, 5);
    this.player.scale.setTo(2,2);

    this.initSpawnPosition();
    this.spawnEnemies();

    this.game.add.existing(this.player);
    this.game.camera.follow(this.player);

    // For development only
    this.fps = this.game.add.text(16, 16, 'FPS: 0', { fontSize: '16px', fill: '#F08' });
    this.fps.fixedToCamera = true;

    this.stats = this.game.add.text(16, 40, '', { fontSize: '16px', fill: '#F08' });
    this.stats.fixedToCamera = true;

    this.health = this.game.add.text(16, 64, '', {fontSize: '16px', fill: '#F08' });
    this.health.fixedToCamera = true;

    this.gameOver = this.game.add.text(this.game.width / 2, this.game.height / 2, '', {fontSize: '48px', fill:'#F08'});
    this.gameOver.fixedToCamera = true;

    Darwinator.Pathfinder = new EasyStar.js();
    //Darwinator.Pathfinder.enableDiagonals();
    var indexes = Darwinator.Helpers.convertTileMap(this.map.layers[0].data);
    Darwinator.Pathfinder.setGrid(indexes);
    Darwinator.Pathfinder.setAcceptableTiles([1337, 168, 156, 157, 158, 172, 173, 174, 188, 189, 190, 205]);

    var x = this.game.width / 2
    , y = this.game.height / 2;
    this.pauseText = this.game.add.text(x, y, 'Game paused', { fontSize: '16px', fill: '#fff', align: 'center' });
    this.pauseText.anchor.setTo(0.5, 0.5);
    this.pauseText.fixedToCamera = true;
    this.pauseText.renderable = false;
    this.pauseText.visible = false;
  },

  loadLevel: function() {
    this.map = this.game.add.tilemap('level1');
    this.map.addTilesetImage('tiles', 'tiles');

    Darwinator.setTileSize(this.map.tileWidth, this.map.tileHeight);

    this.map.setCollisionByExclusion([1337, 168, 156, 157, 158, 172, 173, 174, 188, 189, 190, 205]);
    this.map.createLayer('Tile Layer 2');
    this.layer = this.map.createLayer('Tile Layer 1');
    this.layer.debug = true;

    this.map.collisionLayer = this.layer;
    this.layer.resizeWorld();
  },

  spawnEnemies: function () {
    var spawnIndexes = new Array(this.spawnPositions.length);

    for (var i = 0; i < spawnIndexes.length; i++) {
      spawnIndexes[i] = i;
    }

    var rInd;
    var pos;
    while (this.numberOfEnemies && spawnIndexes.length) {
      rInd = Math.round(Math.random() * spawnIndexes.length -1);
      pos = spawnIndexes.splice(rInd,1);
      this.enemies.add(new Darwinator.Enemy(this.game, this.player,
        this.spawnPositions[pos][0],
        this.spawnPositions[pos][1], 100));
      this.numberOfEnemies--;
    }
  },

  initSpawnPosition: function () {
    var matrix = Darwinator.Helpers.convertTileMap(this.map.layers[0].data);

    this.enemies = this.game.add.group();

    for (var i = 0; i < matrix.length; i++) {
      for(var j = 0; j < matrix[i].length; j++) {
        if (matrix[i][j] === 168){
          this.spawnPositions.push(Darwinator.Helpers.tileToPixels(j,i));
        }
      }
    }
  },

  update: function () {
    // TODO: Move this to the nonexistent resume callback
    if (this.pauseText.visible) this.pauseText.visible = false;

    this.game.physics.collide(this.player, this.layer);
    this.game.physics.collide(this.enemies, this.layer);
    this.game.physics.collide(this.enemies, this.enemies);

    // For development only
    this.fps.content = 'FPS: ' + this.game.time.fps;
    this.stats.content = 'Player stamina: ' + Math.round(this.player.currBreath) + '/' + this.player.stamina;
    this.health.content = 'Health: ' + this.player.health;
  },

  paused: function () {
    this.pauseText.visible = true;
  }

};
<|endoftext|>


<commit_before>var gmail3 = function () {
  var gmail3 = {};
  var msgConsumers = [];

  function addMsgConsumer(msgConsumer) {
    msgConsumers.push(msgConsumer);
  }

  function isEmpty(db, sheet) {
    var rows = objDB.getRows(db, sheet, [], {}, 1);
    if (rows.length === 0) {
      return true;
    } else {
      return false;
    }
  }

  function emailReport(scriptState, msgConsumers) {
    var db = objDB.open(scriptState.ssID);
    Logger.log('Sending last months report via Email');
    for(i = 0; i < msgConsumers.length; i += 1) {
      if (! msgConsumers[i].isEmpty(db)) {
        msgConsumers[i].graphFunction(scriptState);
      }
    }
    var htmlBody = "";
    var inlineImages = {};
    var blob;

    for(i = 0; i < msgConsumers.length; i += 1) {
      if (! msgConsumers[i].isEmpty(db)) {
        htmlBody += "
\n";
        blob = msgConsumers[i].chart.getAs('image/png').setName(msgConsumers[i].name + ".png");
        inlineImages[i] = blob;
      }
    }

    MailApp.sendEmail({
      to: Session.getActiveUser().getEmail(),
      subject: "Email3 - " + scriptState.monthToProcess.format('MMM YYYY'),
      htmlBody: htmlBody,
      inlineImages: inlineImages
    });
    scriptState.reportEmailed = true;
  }

  function createSpreadSheet(monthToProcess) {
    var ssNew = SpreadsheetApp.create("Email3 Data - " + monthToProcess.format('MMM YYYY'));
    var ssID = ssNew.getUrl().split('/')[7];
    // This is needed so we can use the Google Visualization API Query Language
    // to set the data source URL for graphs
    allowPublicViewing(ssID);
    return ssID;
  }

  function initializeSpreadSheet(scriptState) {
    var ss = SpreadsheetApp.openById(scriptState.ssID);
    for(i = 0; i < msgConsumers.length; i += 1) {
      msgConsumers[i].initSpreadSheet(ss);
    }
  }

  function populateData(scriptState, msgConsumers) {
    var db = objDB.open(scriptState.ssID);
    Logger.log('Populating Data');
    // Process up to 100 gmail threads at once
    var batchSize = 100;
    if (scriptState.debugEnabled) {
      // If we have debugEnabled only process 20, so runs are quicker
      batchSize = 20;
    }
    var after = scriptState.monthToProcess.clone().startOf('month').format('YYYY/MM/DD');
    var before = scriptState.monthToProcess.clone().endOf('month').add(1, 'days').format('YYYY/MM/DD');
    var query = "in:anywhere -label:sms -label:call-log -label:chats -label:spam -filename:ics";
    query += " -from:maestro.bounces.google.com -from:unified-notifications.bounces.google.com -from:docs.google.com";
    query += " -from:group.calendar.google.com -from:apps-scripts-notifications@google.com";
    query += " -from:sites.bounces.google.com";
    query += " after:" + after + " before:" + before;

    Logger.log('Searching: ' + query);
    var threads = GmailApp.search(query, scriptState.threadIndex, batchSize);
    if (scriptState.debugEnabled && scriptState.threadIndex > 200) {
      scriptState.dataPopulated = true;
    } else if (threads.length === 0) {
      scriptState.dataPopulated = true;
    } else {
      for (thread = 0; thread < threads.length; thread += 1) {
        var msg = threads[thread].getMessages()[0];
        for(var i = 0; i < msgConsumers.length; i += 1) {
          if (scriptState.debugEnabled) {
            Logger.log('Calling Message function for, ' + msgConsumers[i].name);
          }
          try {
            msgConsumers[i].msgFunction(msg, db);
          } catch (e) {
            throw new Error("msgConsumer, " + msgConsumers[i].name + ", threw error: " + e.message);
          }
        }
      }
    }
    scriptState.threadIndex += batchSize;
    Logger.log('PopulateData run complete: threads: ' + threads.length + ', threadIndex: ' + scriptState.threadIndex);
  }

  function setScriptState(scriptState) {
    var scriptStateString = JSON.stringify(scriptState);
    PropertiesService.getUserProperties().setProperty("scriptState", scriptStateString);
    Logger.log("New scriptState set: " + scriptStateString);
  }

  function getScriptState() {
    var scriptState = null;
    var nextMonthToProcess;
    var scriptStateString = PropertiesService.getUserProperties().getProperty("scriptState");
    var debugEnabledUserProperty = PropertiesService.getUserProperties().getProperty("debugEnabled");
    if (debugEnabledUserProperty === "true") {
      debugEnabled = true;
      Logger.log("Debugging enabled");
    } else {
      debugEnabled = false;
      Logger.log("Debugging disabled");
    }
    Logger.log("Retrieved scriptState: " + scriptStateString);
    if (scriptStateString === null) {
      Logger.log('No stored scriptState, creating an empty one');
      scriptState = {};
      scriptState.debugEnabled = debugEnabled;
      var currentMonth = moment().startOf('month');
      if (scriptState.debugEnabled) {
        nextMonthToProcess = currentMonth.clone().startOf('year');
      } else {
        nextMonthToProcess = currentMonth.clone().subtract(1, 'days').startOf('month');
      }
      scriptState.ssID = createSpreadSheet(nextMonthToProcess);
      initializeSpreadSheet(scriptState);
      scriptState.monthToProcess = nextMonthToProcess;
      scriptState.dataPopulated = false;
      scriptState.reportEmailed = false;
      scriptState.threadIndex = 0;
      scriptState.triggers = [];
      scriptState.dailyRunningTimeTotalSeconds = 0;
      scriptState.currentDay = moment().startOf('day');
    } else {
      scriptState = JSON.parse(scriptStateString);
      scriptState.debugEnabled = debugEnabled;
      scriptState.monthToProcess = moment(scriptState.monthToProcess);
      scriptState.currentDay = moment(scriptState.currentDay);
    }

    // Reset the running total, if it is a new day
    if (! moment().startOf('day').isSame(scriptState.currentDay)) {
      scriptState.dailyRunningTimeTotalSeconds = 0;
      scriptState.currentDay = moment().startOf('day');
    }

    // Create a daily trigger if it does not exist
    dailyTrigger = _.find(scriptState.triggers, function (trigger) {
      return trigger.type === "atHour";
    });
    if (dailyTrigger === undefined) {
      Logger.log("No daily trigger, adding one");
      trigger = ScriptApp.newTrigger("main")
      .timeBased()
      .atHour(1)
      .everyDays(1)
      .create();
      scriptState.triggers.push({
        type: "atHour",
        uniqueId: trigger.getUniqueId(),
      });
    }

    return scriptState;
  }

  function deleteSheet1(scriptState) {
    var ss = SpreadsheetApp.openById(scriptState.ssID);
    if (ss.getSheetByName("Sheet1") !== null) {
      ss.deleteSheet(ss.getSheetByName("Sheet1"));
    }
  }

  function incrementMonth(scriptState) {
    Logger.log('Processing done for the current month, incrementing the month');
    var nextMonthToProcess = scriptState.monthToProcess.clone()
    .endOf('month')
    .add(1, 'days')
    .startOf('month');
    // This may not suceeed so do it first, before changing the script state
    scriptState.ssID = createSpreadSheet(nextMonthToProcess);
    initializeSpreadSheet(scriptState);
    scriptState.monthToProcess = nextMonthToProcess;
    scriptState.dataPopulated = false;
    scriptState.reportEmailed = false;
    scriptState.threadIndex = 0;
    scriptState.dailyRunningTimeTotalSeconds = 0;
    scriptState.currentDay = moment().startOf('day');

    return scriptState;
  }

  function deleteAtTriggers(scriptState) {
    Logger.log("Deleting all existing at triggers");
    var trigger;
    function uniqueIdMatchProjectTrigger(projectTrigger) {
      return function (trigger) {
        return trigger.uniqueId === projectTrigger.getUniqueId();
      };
    }
    function uniqueIdMatch(uniqueId) {
      return function (trigger) {
        return trigger.uniqueId === uniqueId;
      };
    }
    var projectTriggers = ScriptApp.getProjectTriggers();
    for (var i = 0; i < projectTriggers.length; i++) {
      trigger = _.find(scriptState.triggers, uniqueIdMatchProjectTrigger(projectTriggers[i]));
      if (trigger === undefined) {
        // We have no record of this trigger, so delete it
        ScriptApp.deleteTrigger(projectTriggers[i]);
      } else {
        if (trigger.type === "at") {
          var uniqueId = projectTriggers[i].getUniqueId();
          ScriptApp.deleteTrigger(projectTriggers[i]);
          scriptState.triggers = _.reject(scriptState.triggers, uniqueIdMatch(uniqueId));
        }
      }
    }
  }

  function setupNextAtTrigger(scriptState) {
    // Delete any previous at triggers, so we don't exceed the trigger quota
    deleteAtTriggers(scriptState);

    // If less than daily run time, 3 hours, and there is still time left in the
    // day, add a new trigger
    if (scriptState.dailyRunningTimeTotalSeconds < (170 * 60) &&
      moment().add(35, 'minutes').date() === moment().date()) {
      Logger.log("Scheduling a new at trigger at: " + moment().add(15, "minutes").toISOString());
      trigger = ScriptApp.newTrigger("main").timeBased().after(15 * 60 * 1000).create();
      scriptState.triggers.push({
        type: "at",
        uniqueId: trigger.getUniqueId(),
      });
    } else {
      Logger.log("Not scheduling any further triggers for today to avoid exceeding execution quota of 3 hours");
      Logger.log("Running time total today " + (scriptState.dailyRunningTimeTotalSeconds / 60) + " minutes");
    }
  }

  function extractEmailAddress(emailAddress) {
    var emailAddressRegex = /^(?:.*<)?([^<>]+)(?:>)?$/;
    return emailAddressRegex.exec(emailAddress)[1].toLowerCase();
  }

  function unfoldHeaders(foldedHeaders) {
    var unfoldRegex = /\r\n[ \t]+/g;
    return foldedHeaders.replace(unfoldRegex, " ");
  }

  function extractHeaders(rawMessage) {
    var headers = {};
    var parseHeaderRegex = /^[ \n\t]*([^:]+):[ \t]*(.*)$/;
    var extractHeadersRegex = /\r\n\r\n/;
    var printableRegex = /[^ -~]+/g;
    var foldedHeaders = rawMessage.split(extractHeadersRegex)[0];
    var unfoldedHeaders = unfoldHeaders(foldedHeaders);
    var headerLines = unfoldedHeaders.split(/\r\n/);
    for (var i = 0; i < headerLines.length; i++) {
      var printableHeader = headerLines[i].replace(printableRegex, "");
      var headerMatch = parseHeaderRegex.exec(printableHeader);
      if (headerMatch === null) {
        throw new Error("headerMatch returned null");
      }
      if (headerMatch[1] !== "") {
        var headerField = headerMatch[1].toLowerCase();
        if (headers.hasOwnProperty(headerField)) {
          headers[headerField].push(headerMatch[2]);
        } else {
          headers[headerField] = [headerMatch[2]];
        }
      }
    }
    return headers;
  }

  function allowPublicViewing(ID) {
    file = DriveApp.getFileById(ID);
    file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
  }

  // These are admittedly swiss cheese tests for robots, but I am at loss to
  // find better methods.
  function emailSentByRobot(rawMessage) {
    var msgFromRobot = false;
    var headers = extractHeaders(rawMessage);
    var robotMailerRegex = /\s\(Postfix/;
    var fromRobots = [
      /^no-?reply@.*$/,
      /^alert@pingdom.com$/,
    ];
    if (headers.hasOwnProperty("received")) {
      var firstHop = headers.received[headers.received.length - 1];
      if (robotMailerRegex.test(firstHop)) {
        msgFromRobot = true;
      }
    }
    for (var i = 0; i < fromRobots.length; i++) {
      if (fromRobots[i].test(headers.from)) {
        msgFromRobot = true;
        break;
      }
    }
    return msgFromRobot;
  }

  function main() {
    var lock = LockService.getScriptLock();
    if (!lock.tryLock(1000)) {
      Logger.log('Could not obtain lock after a second');
      return;
    }
    var currentMonth = moment().startOf('month');
    var scriptStartTime = moment();
    var scriptState = null;

    try {
      scriptState = getScriptState();
    } catch (e) {
      Logger.log('Error: ' + e.message);
      return;
    }

    if (scriptState.monthToProcess.isBefore(currentMonth)) {
      Logger.log("Beginning processing of: Email3 - " + scriptState.monthToProcess.format('MMM YYYY'));
      if (scriptState.dataPopulated) {
        if (scriptState.reportEmailed) {
          try {
            deleteSheet1(scriptState);
          } catch (e) {
            Logger.log('Error: Unable to delete Sheet1 for the previous month: ' + e.message);
          }
          try {
            incrementMonth(scriptState);
          } catch (e) {
            Logger.log('Error: Unable to increment month: ' + e.message);
          }
        } else {
          try {
            emailReport(scriptState, msgConsumers);
          } catch (e) {
            Logger.log('Error: Unable to email report for the previous month: ' + e.message);
          }
        }
      } else {
        try {
          populateData(scriptState, msgConsumers);
        } catch (e) {
          Logger.log('Error: Unable to populate data: ' + e.message);
        }
      }
      scriptState.dailyRunningTimeTotalSeconds += moment().diff(scriptStartTime, 'seconds');
      try {
        setupNextAtTrigger(scriptState);
      } catch (e) {
        Logger.log('Error: Unable to schedule next at trigger: ' + e.message);
      }
    } else {
      Logger.log('Previous month processed complete, nothing todo');
    }

    for (var i = 0; i < 5; i++) {
      try {
        setScriptState(scriptState);
        break;
      } catch (e) {
        Logger.log('Error: Unable to set script state: ' + e.message);
      }
    }
    lock.releaseLock();
  }

  gmail3.emailReport = emailReport;
  gmail3.addMsgConsumer = addMsgConsumer;
  gmail3.createSpreadSheet = createSpreadSheet;
  gmail3.initializeSpreadSheet = initializeSpreadSheet;
  gmail3.isEmpty = isEmpty;
  gmail3.populateData = populateData;
  gmail3.setScriptState = setScriptState;
  gmail3.getScriptState = getScriptState;
  gmail3.deleteSheet1 = deleteSheet1;
  gmail3.incrementMonth = incrementMonth;
  gmail3.deleteAtTriggers = deleteAtTriggers;
  gmail3.setupNextAtTrigger = setupNextAtTrigger;
  gmail3.extractEmailAddress = extractEmailAddress;
  gmail3.unfoldHeaders = unfoldHeaders;
  gmail3.extractHeaders = extractHeaders;
  gmail3.allowPublicViewing = allowPublicViewing;
  gmail3.emailSentByRobot = emailSentByRobot;
  gmail3.main = main;

  return gmail3;
}();
<commit_msg>Only process 40 threads if in debug mode<commit_after>var gmail3 = function () {
  var gmail3 = {};
  var msgConsumers = [];

  function addMsgConsumer(msgConsumer) {
    msgConsumers.push(msgConsumer);
  }

  function isEmpty(db, sheet) {
    var rows = objDB.getRows(db, sheet, [], {}, 1);
    if (rows.length === 0) {
      return true;
    } else {
      return false;
    }
  }

  function emailReport(scriptState, msgConsumers) {
    var db = objDB.open(scriptState.ssID);
    Logger.log('Sending last months report via Email');
    for(i = 0; i < msgConsumers.length; i += 1) {
      if (! msgConsumers[i].isEmpty(db)) {
        msgConsumers[i].graphFunction(scriptState);
      }
    }
    var htmlBody = "";
    var inlineImages = {};
    var blob;

    for(i = 0; i < msgConsumers.length; i += 1) {
      if (! msgConsumers[i].isEmpty(db)) {
        htmlBody += "
\n";
        blob = msgConsumers[i].chart.getAs('image/png').setName(msgConsumers[i].name + ".png");
        inlineImages[i] = blob;
      }
    }

    MailApp.sendEmail({
      to: Session.getActiveUser().getEmail(),
      subject: "Email3 - " + scriptState.monthToProcess.format('MMM YYYY'),
      htmlBody: htmlBody,
      inlineImages: inlineImages
    });
    scriptState.reportEmailed = true;
  }

  function createSpreadSheet(monthToProcess) {
    var ssNew = SpreadsheetApp.create("Email3 Data - " + monthToProcess.format('MMM YYYY'));
    var ssID = ssNew.getUrl().split('/')[7];
    // This is needed so we can use the Google Visualization API Query Language
    // to set the data source URL for graphs
    allowPublicViewing(ssID);
    return ssID;
  }

  function initializeSpreadSheet(scriptState) {
    var ss = SpreadsheetApp.openById(scriptState.ssID);
    for(i = 0; i < msgConsumers.length; i += 1) {
      msgConsumers[i].initSpreadSheet(ss);
    }
  }

  function populateData(scriptState, msgConsumers) {
    var db = objDB.open(scriptState.ssID);
    Logger.log('Populating Data');
    // Process up to 100 gmail threads at once
    var batchSize = 100;
    if (scriptState.debugEnabled) {
      // If we have debugEnabled only process 20, so runs are quicker
      batchSize = 20;
    }
    var after = scriptState.monthToProcess.clone().startOf('month').format('YYYY/MM/DD');
    var before = scriptState.monthToProcess.clone().endOf('month').add(1, 'days').format('YYYY/MM/DD');
    var query = "in:anywhere -label:sms -label:call-log -label:chats -label:spam -filename:ics";
    query += " -from:maestro.bounces.google.com -from:unified-notifications.bounces.google.com -from:docs.google.com";
    query += " -from:group.calendar.google.com -from:apps-scripts-notifications@google.com";
    query += " -from:sites.bounces.google.com";
    query += " after:" + after + " before:" + before;

    Logger.log('Searching: ' + query);
    var threads = GmailApp.search(query, scriptState.threadIndex, batchSize);
    if (scriptState.debugEnabled && scriptState.threadIndex >= 40) {
      scriptState.dataPopulated = true;
    } else if (threads.length === 0) {
      scriptState.dataPopulated = true;
    } else {
      for (thread = 0; thread < threads.length; thread += 1) {
        var msg = threads[thread].getMessages()[0];
        for(var i = 0; i < msgConsumers.length; i += 1) {
          if (scriptState.debugEnabled) {
            Logger.log('Calling Message function for, ' + msgConsumers[i].name);
          }
          try {
            msgConsumers[i].msgFunction(msg, db);
          } catch (e) {
            throw new Error("msgConsumer, " + msgConsumers[i].name + ", threw error: " + e.message);
          }
        }
      }
    }
    scriptState.threadIndex += batchSize;
    Logger.log('PopulateData run complete: threads: ' + threads.length + ', threadIndex: ' + scriptState.threadIndex);
  }

  function setScriptState(scriptState) {
    var scriptStateString = JSON.stringify(scriptState);
    PropertiesService.getUserProperties().setProperty("scriptState", scriptStateString);
    Logger.log("New scriptState set: " + scriptStateString);
  }

  function getScriptState() {
    var scriptState = null;
    var nextMonthToProcess;
    var scriptStateString = PropertiesService.getUserProperties().getProperty("scriptState");
    var debugEnabledUserProperty = PropertiesService.getUserProperties().getProperty("debugEnabled");
    if (debugEnabledUserProperty === "true") {
      debugEnabled = true;
      Logger.log("Debugging enabled");
    } else {
      debugEnabled = false;
      Logger.log("Debugging disabled");
    }
    Logger.log("Retrieved scriptState: " + scriptStateString);
    if (scriptStateString === null) {
      Logger.log('No stored scriptState, creating an empty one');
      scriptState = {};
      scriptState.debugEnabled = debugEnabled;
      var currentMonth = moment().startOf('month');
      if (scriptState.debugEnabled) {
        nextMonthToProcess = currentMonth.clone().startOf('year');
      } else {
        nextMonthToProcess = currentMonth.clone().subtract(1, 'days').startOf('month');
      }
      scriptState.ssID = createSpreadSheet(nextMonthToProcess);
      initializeSpreadSheet(scriptState);
      scriptState.monthToProcess = nextMonthToProcess;
      scriptState.dataPopulated = false;
      scriptState.reportEmailed = false;
      scriptState.threadIndex = 0;
      scriptState.triggers = [];
      scriptState.dailyRunningTimeTotalSeconds = 0;
      scriptState.currentDay = moment().startOf('day');
    } else {
      scriptState = JSON.parse(scriptStateString);
      scriptState.debugEnabled = debugEnabled;
      scriptState.monthToProcess = moment(scriptState.monthToProcess);
      scriptState.currentDay = moment(scriptState.currentDay);
    }

    // Reset the running total, if it is a new day
    if (! moment().startOf('day').isSame(scriptState.currentDay)) {
      scriptState.dailyRunningTimeTotalSeconds = 0;
      scriptState.currentDay = moment().startOf('day');
    }

    // Create a daily trigger if it does not exist
    dailyTrigger = _.find(scriptState.triggers, function (trigger) {
      return trigger.type === "atHour";
    });
    if (dailyTrigger === undefined) {
      Logger.log("No daily trigger, adding one");
      trigger = ScriptApp.newTrigger("main")
      .timeBased()
      .atHour(1)
      .everyDays(1)
      .create();
      scriptState.triggers.push({
        type: "atHour",
        uniqueId: trigger.getUniqueId(),
      });
    }

    return scriptState;
  }

  function deleteSheet1(scriptState) {
    var ss = SpreadsheetApp.openById(scriptState.ssID);
    if (ss.getSheetByName("Sheet1") !== null) {
      ss.deleteSheet(ss.getSheetByName("Sheet1"));
    }
  }

  function incrementMonth(scriptState) {
    Logger.log('Processing done for the current month, incrementing the month');
    var nextMonthToProcess = scriptState.monthToProcess.clone()
    .endOf('month')
    .add(1, 'days')
    .startOf('month');
    // This may not suceeed so do it first, before changing the script state
    scriptState.ssID = createSpreadSheet(nextMonthToProcess);
    initializeSpreadSheet(scriptState);
    scriptState.monthToProcess = nextMonthToProcess;
    scriptState.dataPopulated = false;
    scriptState.reportEmailed = false;
    scriptState.threadIndex = 0;
    scriptState.dailyRunningTimeTotalSeconds = 0;
    scriptState.currentDay = moment().startOf('day');

    return scriptState;
  }

  function deleteAtTriggers(scriptState) {
    Logger.log("Deleting all existing at triggers");
    var trigger;
    function uniqueIdMatchProjectTrigger(projectTrigger) {
      return function (trigger) {
        return trigger.uniqueId === projectTrigger.getUniqueId();
      };
    }
    function uniqueIdMatch(uniqueId) {
      return function (trigger) {
        return trigger.uniqueId === uniqueId;
      };
    }
    var projectTriggers = ScriptApp.getProjectTriggers();
    for (var i = 0; i < projectTriggers.length; i++) {
      trigger = _.find(scriptState.triggers, uniqueIdMatchProjectTrigger(projectTriggers[i]));
      if (trigger === undefined) {
        // We have no record of this trigger, so delete it
        ScriptApp.deleteTrigger(projectTriggers[i]);
      } else {
        if (trigger.type === "at") {
          var uniqueId = projectTriggers[i].getUniqueId();
          ScriptApp.deleteTrigger(projectTriggers[i]);
          scriptState.triggers = _.reject(scriptState.triggers, uniqueIdMatch(uniqueId));
        }
      }
    }
  }

  function setupNextAtTrigger(scriptState) {
    // Delete any previous at triggers, so we don't exceed the trigger quota
    deleteAtTriggers(scriptState);

    // If less than daily run time, 3 hours, and there is still time left in the
    // day, add a new trigger
    if (scriptState.dailyRunningTimeTotalSeconds < (170 * 60) &&
      moment().add(35, 'minutes').date() === moment().date()) {
      Logger.log("Scheduling a new at trigger at: " + moment().add(15, "minutes").toISOString());
      trigger = ScriptApp.newTrigger("main").timeBased().after(15 * 60 * 1000).create();
      scriptState.triggers.push({
        type: "at",
        uniqueId: trigger.getUniqueId(),
      });
    } else {
      Logger.log("Not scheduling any further triggers for today to avoid exceeding execution quota of 3 hours");
      Logger.log("Running time total today " + (scriptState.dailyRunningTimeTotalSeconds / 60) + " minutes");
    }
  }

  function extractEmailAddress(emailAddress) {
    var emailAddressRegex = /^(?:.*<)?([^<>]+)(?:>)?$/;
    return emailAddressRegex.exec(emailAddress)[1].toLowerCase();
  }

  function unfoldHeaders(foldedHeaders) {
    var unfoldRegex = /\r\n[ \t]+/g;
    return foldedHeaders.replace(unfoldRegex, " ");
  }

  function extractHeaders(rawMessage) {
    var headers = {};
    var parseHeaderRegex = /^[ \n\t]*([^:]+):[ \t]*(.*)$/;
    var extractHeadersRegex = /\r\n\r\n/;
    var printableRegex = /[^ -~]+/g;
    var foldedHeaders = rawMessage.split(extractHeadersRegex)[0];
    var unfoldedHeaders = unfoldHeaders(foldedHeaders);
    var headerLines = unfoldedHeaders.split(/\r\n/);
    for (var i = 0; i < headerLines.length; i++) {
      var printableHeader = headerLines[i].replace(printableRegex, "");
      var headerMatch = parseHeaderRegex.exec(printableHeader);
      if (headerMatch === null) {
        throw new Error("headerMatch returned null");
      }
      if (headerMatch[1] !== "") {
        var headerField = headerMatch[1].toLowerCase();
        if (headers.hasOwnProperty(headerField)) {
          headers[headerField].push(headerMatch[2]);
        } else {
          headers[headerField] = [headerMatch[2]];
        }
      }
    }
    return headers;
  }

  function allowPublicViewing(ID) {
    file = DriveApp.getFileById(ID);
    file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
  }

  // These are admittedly swiss cheese tests for robots, but I am at loss to
  // find better methods.
  function emailSentByRobot(rawMessage) {
    var msgFromRobot = false;
    var headers = extractHeaders(rawMessage);
    var robotMailerRegex = /\s\(Postfix/;
    var fromRobots = [
      /^no-?reply@.*$/,
      /^alert@pingdom.com$/,
    ];
    if (headers.hasOwnProperty("received")) {
      var firstHop = headers.received[headers.received.length - 1];
      if (robotMailerRegex.test(firstHop)) {
        msgFromRobot = true;
      }
    }
    for (var i = 0; i < fromRobots.length; i++) {
      if (fromRobots[i].test(headers.from)) {
        msgFromRobot = true;
        break;
      }
    }
    return msgFromRobot;
  }

  function main() {
    var lock = LockService.getScriptLock();
    if (!lock.tryLock(1000)) {
      Logger.log('Could not obtain lock after a second');
      return;
    }
    var currentMonth = moment().startOf('month');
    var scriptStartTime = moment();
    var scriptState = null;

    try {
      scriptState = getScriptState();
    } catch (e) {
      Logger.log('Error: ' + e.message);
      return;
    }

    if (scriptState.monthToProcess.isBefore(currentMonth)) {
      Logger.log("Beginning processing of: Email3 - " + scriptState.monthToProcess.format('MMM YYYY'));
      if (scriptState.dataPopulated) {
        if (scriptState.reportEmailed) {
          try {
            deleteSheet1(scriptState);
          } catch (e) {
            Logger.log('Error: Unable to delete Sheet1 for the previous month: ' + e.message);
          }
          try {
            incrementMonth(scriptState);
          } catch (e) {
            Logger.log('Error: Unable to increment month: ' + e.message);
          }
        } else {
          try {
            emailReport(scriptState, msgConsumers);
          } catch (e) {
            Logger.log('Error: Unable to email report for the previous month: ' + e.message);
          }
        }
      } else {
        try {
          populateData(scriptState, msgConsumers);
        } catch (e) {
          Logger.log('Error: Unable to populate data: ' + e.message);
        }
      }
      scriptState.dailyRunningTimeTotalSeconds += moment().diff(scriptStartTime, 'seconds');
      try {
        setupNextAtTrigger(scriptState);
      } catch (e) {
        Logger.log('Error: Unable to schedule next at trigger: ' + e.message);
      }
    } else {
      Logger.log('Previous month processed complete, nothing todo');
    }

    for (var i = 0; i < 5; i++) {
      try {
        setScriptState(scriptState);
        break;
      } catch (e) {
        Logger.log('Error: Unable to set script state: ' + e.message);
      }
    }
    lock.releaseLock();
  }

  gmail3.emailReport = emailReport;
  gmail3.addMsgConsumer = addMsgConsumer;
  gmail3.createSpreadSheet = createSpreadSheet;
  gmail3.initializeSpreadSheet = initializeSpreadSheet;
  gmail3.isEmpty = isEmpty;
  gmail3.populateData = populateData;
  gmail3.setScriptState = setScriptState;
  gmail3.getScriptState = getScriptState;
  gmail3.deleteSheet1 = deleteSheet1;
  gmail3.incrementMonth = incrementMonth;
  gmail3.deleteAtTriggers = deleteAtTriggers;
  gmail3.setupNextAtTrigger = setupNextAtTrigger;
  gmail3.extractEmailAddress = extractEmailAddress;
  gmail3.unfoldHeaders = unfoldHeaders;
  gmail3.extractHeaders = extractHeaders;
  gmail3.allowPublicViewing = allowPublicViewing;
  gmail3.emailSentByRobot = emailSentByRobot;
  gmail3.main = main;

  return gmail3;
}();
<|endoftext|>


<commit_before>var Game = function(items) {
  this.r1 = 50;
  this.g1 = 0;
  this.totalClicks = 0;
  this.items = items;

  this.click = function(id) {
    return function (evt) {
      this.totalClicks++;
      this[id]++;
      num('t' + id, this[id]);
    }.bind(this);
  };

  this.forin = function (obj, callback) {
    forin(obj, callback.bind(this));
  };

  this.spend = function (id) {
    return function (evt) {
      var itemInfo = this.items[id];
      var noMonies = false;
      this.forin(
        itemInfo.price,
        function (price, ii) {
          if (this[ii] < price) {
            noMonies = true;
          }
        }
      );
      if (noMonies) {
        console.log("No Monies!");
        return;
      }
      this.forin(
        itemInfo.price,
        function (price, ii, item) {
          this[ii] = this[ii] - price;
          this.items[id].price[ii] *= this.items[id].priceJump;
          num('t' + ii, this[ii]);
          num("c" + id, this.items[id].price[ii]);
        }
      );

      this.items[id].owned++;
      num('t' + id,  this.items[id].owned);
      num("o" + id, this.items[id].owned);
      this.totalClicks++;
    }.bind(this);
  };

  this.sell = function (id) {
    return function (evt) {
      var item = this.items[id];
      if (item.owned > 0) {
        this.items[id].owned -= 1;
        num("t" + item.good, g[item.good]);
        num("o" + id, item.owned);
        console.log("You don't own any");
        return;
      }
    }.bind(this);
  };

  this.bindSpend = function(id) {
    bind(gId(id),'click', this.spend(id));
    this.bindSell(id);
  };

  this.bindClick= function(id) {
    bind(gId(id),'click', this.click(id));
  };

  this.bindSell = function(id) {
    var btn = gId("s" + id);
    if (btn) {
      bind(btn,'click', this.sell(id));
    }
  };

  var constructor = (function (g) {
    g.bindClick('r1');
    g.bindSpend('i1');
    g.bindSpend('g1');

    num('tr1', g.r1);
    num('ti1', g.items.i1.owned);

    setInterval(
      function () {
        var ii;
        for (ii in g.items) {
          if (g.items.hasOwnProperty(ii)) {
            var item = g.items[ii];
            if (item.type === 'resource') {
              g[item.resource] += item.owned * item.modifier;
              num("t" + item.resource, g[item.resource]);
            } else if(item.type === 'good' &&
                      item.owned > 0) {
              var jj = 0;
              while (g[item.resource] >= item.resourceCost &&
                    jj <= item.owned) {
                jj += 1;
                g[item.resource] -= item.resourceCost * item.owned;
                g[item.good] += item.owned;
                num("t" + item.good, g[item.good]);
                num("o" + item.good, item.owned);
                num("t" + item.resource, g[item.resource]);

              }
            }
          }
        }
      }, 1000);
  }(this));
};

g = new Game(Gitems);<commit_msg>fix off by one bug in converting resources<commit_after>var Game = function(items) {
  this.r1 = 50;
  this.g1 = 0;
  this.totalClicks = 0;
  this.items = items;

  this.click = function(id) {
    return function (evt) {
      this.totalClicks++;
      this[id]++;
      num('t' + id, this[id]);
    }.bind(this);
  };

  this.forin = function (obj, callback) {
    forin(obj, callback.bind(this));
  };

  this.spend = function (id) {
    return function (evt) {
      var itemInfo = this.items[id];
      var noMonies = false;
      this.forin(
        itemInfo.price,
        function (price, ii) {
          if (this[ii] < price) {
            noMonies = true;
          }
        }
      );
      if (noMonies) {
        console.log("No Monies!");
        return;
      }
      this.forin(
        itemInfo.price,
        function (price, ii, item) {
          this[ii] = this[ii] - price;
          this.items[id].price[ii] *= this.items[id].priceJump;
          num('t' + ii, this[ii]);
          num("c" + id, this.items[id].price[ii]);
        }
      );

      this.items[id].owned++;
      num('t' + id,  this.items[id].owned);
      num("o" + id, this.items[id].owned);
      this.totalClicks++;
    }.bind(this);
  };

  this.sell = function (id) {
    return function (evt) {
      var item = this.items[id];
      if (item.owned > 0) {
        this.items[id].owned -= 1;
        num("t" + item.good, g[item.good]);
        num("o" + id, item.owned);
        console.log("You don't own any");
        return;
      }
    }.bind(this);
  };

  this.bindSpend = function(id) {
    bind(gId(id),'click', this.spend(id));
    this.bindSell(id);
  };

  this.bindClick= function(id) {
    bind(gId(id),'click', this.click(id));
  };

  this.bindSell = function(id) {
    var btn = gId("s" + id);
    if (btn) {
      bind(btn,'click', this.sell(id));
    }
  };

  var constructor = (function (g) {
    g.bindClick('r1');
    g.bindSpend('i1');
    g.bindSpend('g1');

    num('tr1', g.r1);
    num('ti1', g.items.i1.owned);

    setInterval(
      function () {
        var ii;
        for (ii in g.items) {
          if (g.items.hasOwnProperty(ii)) {
            var item = g.items[ii];
            if (item.type === 'resource') {
              g[item.resource] += item.owned * item.modifier;
              num("t" + item.resource, g[item.resource]);
            } else if(item.type === 'good' &&
                      item.owned > 0) {
              var jj = 0;
              while (g[item.resource] - item.resourceCost > 0 &&
                    jj <= item.owned) {
                jj += 1;
                g[item.resource] -= item.resourceCost * item.owned;
                g[item.good] += item.owned;
                num("t" + item.good, g[item.good]);
                num("o" + item.good, item.owned);
                num("t" + item.resource, g[item.resource]);

              }
            }
          }
        }
      }, 1000);
  }(this));
};

g = new Game(Gitems);<|endoftext|>


<commit_before>(function($) {
    $(function() {
        // convert rgb to hex value string
        function rgb2hex(rgb) {
            if (/^#[0-9A-F]{6}$/i.test(rgb)) {
                return rgb;
            }

            rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);

            if (rgb === null) {
                return "N/A";
            }

            function hex(x) {
                return ("0" + parseInt(x).toString(16)).slice(-2);
            }

            return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
        }

        $('.dynamic-color .col').each(function() {
            $(this).children().each(function() {
                var color = $(this).css('background-color'),
                    classes = $(this).attr('class');
                $(this).html(rgb2hex(color) + " " + classes);
                if (classes.indexOf("darken") >= 0 || $(this).hasClass('black')) {
                    $(this).css('color', 'rgba(255,255,255,.9');
                }
            });
        });

        // Floating-Fixed table of contents
        setTimeout(function() {
            var tocWrapperHeight = 260; // Max height of ads.
            var tocHeight = $('.toc-wrapper .table-of-contents').length ? $('.toc-wrapper .table-of-contents').height() : 0;
            var socialHeight = 95; // Height of unloaded social media in footer.
            var footerOffset = $('body > footer').first().length ? $('body > footer').first().offset().top : 0;
            var bottomOffset = footerOffset - socialHeight - tocHeight - tocWrapperHeight;

            if ($('nav').length) {
                $('.toc-wrapper').pushpin({
                    top: $('nav').height(),
                    bottom: bottomOffset
                });
            } else if ($('#index-banner').length) {
                $('.toc-wrapper').pushpin({
                    top: $('#index-banner').height(),
                    bottom: bottomOffset
                });
            } else {
                $('.toc-wrapper').pushpin({
                    top: 0,
                    bottom: bottomOffset
                });
            }
        }, 100);

        // Toggle Flow Text
        var toggleFlowTextButton = $('#flow-toggle');
        toggleFlowTextButton.click(function() {
            $('#flow-text-demo').children('p').each(function() {
                $(this).toggleClass('flow-text');
            });
        });

        //    Toggle Containers on page
        var toggleContainersButton = $('#container-toggle-button');
        toggleContainersButton.click(function() {
            $('body .browser-window .container, .had-container').each(function() {
                $(this).toggleClass('had-container');
                $(this).toggleClass('container');
                if ($(this).hasClass('container')) {
                    toggleContainersButton.text("Turn off Containers");
                } else {
                    toggleContainersButton.text("Turn on Containers");
                }
            });
        });

        // Detect touch screen and enable scrollbar if necessary
        function is_touch_device() {
            try {
                document.createEvent("TouchEvent");
                return true;
            } catch (e) {
                return false;
            }
        }
        if (is_touch_device()) {
            $('#nav-mobile').css({ overflow: 'auto' });
        }

        // Plugin initialization
        $('.scrollspy').scrollSpy({scrollOffset:'10'});
        $('.button-collapse').sideNav();
        $('.collapsible').collapsible();
        $('.materialboxed').materialbox();
        $('.parallax').parallax();
    }); // end of document ready
})(jQuery); // end of jQuery name space

//add typekit
(function(d) {
    var config = {
      kitId: 'xpl3urw',
      scriptTimeout: 3000,
      async: true
    },
    h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
  })(document);<commit_msg>add typekit timeout & init lazyload<commit_after>(function($) {
    $(function() {
        // convert rgb to hex value string
        function rgb2hex(rgb) {
            if (/^#[0-9A-F]{6}$/i.test(rgb)) {
                return rgb;
            }

            rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);

            if (rgb === null) {
                return "N/A";
            }

            function hex(x) {
                return ("0" + parseInt(x).toString(16)).slice(-2);
            }

            return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
        }

        $('.dynamic-color .col').each(function() {
            $(this).children().each(function() {
                var color = $(this).css('background-color'),
                    classes = $(this).attr('class');
                $(this).html(rgb2hex(color) + " " + classes);
                if (classes.indexOf("darken") >= 0 || $(this).hasClass('black')) {
                    $(this).css('color', 'rgba(255,255,255,.9');
                }
            });
        });

        // Floating-Fixed table of contents
        setTimeout(function() {
            var tocWrapperHeight = 260; // Max height of ads.
            var tocHeight = $('.toc-wrapper .table-of-contents').length ? $('.toc-wrapper .table-of-contents').height() : 0;
            var socialHeight = 95; // Height of unloaded social media in footer.
            var footerOffset = $('body > footer').first().length ? $('body > footer').first().offset().top : 0;
            var bottomOffset = footerOffset - socialHeight - tocHeight - tocWrapperHeight;

            if ($('nav').length) {
                $('.toc-wrapper').pushpin({
                    top: $('nav').height(),
                    bottom: bottomOffset
                });
            } else if ($('#index-banner').length) {
                $('.toc-wrapper').pushpin({
                    top: $('#index-banner').height(),
                    bottom: bottomOffset
                });
            } else {
                $('.toc-wrapper').pushpin({
                    top: 0,
                    bottom: bottomOffset
                });
            }
        }, 100);

        // Toggle Flow Text
        var toggleFlowTextButton = $('#flow-toggle');
        toggleFlowTextButton.click(function() {
            $('#flow-text-demo').children('p').each(function() {
                $(this).toggleClass('flow-text');
            });
        });

        //    Toggle Containers on page
        var toggleContainersButton = $('#container-toggle-button');
        toggleContainersButton.click(function() {
            $('body .browser-window .container, .had-container').each(function() {
                $(this).toggleClass('had-container');
                $(this).toggleClass('container');
                if ($(this).hasClass('container')) {
                    toggleContainersButton.text("Turn off Containers");
                } else {
                    toggleContainersButton.text("Turn on Containers");
                }
            });
        });

        // Detect touch screen and enable scrollbar if necessary
        function is_touch_device() {
            try {
                document.createEvent("TouchEvent");
                return true;
            } catch (e) {
                return false;
            }
        }
        if (is_touch_device()) {
            $('#nav-mobile').css({ overflow: 'auto' });
        }
        // Plugin initialization
        $('.scrollspy').scrollSpy({scrollOffset:'10'});
        $('.button-collapse').sideNav();
        $('.collapsible').collapsible();
        $('.materialboxed').materialbox();
        $('.parallax').parallax();
        $('img.lazy').lazyload();
    }); // end of document ready
})(jQuery); // end of jQuery name space

//add typekit
(function(d) {
    var config = {
      kitId: 'xpl3urw',
      scriptTimeout: 5000,
      async: true
    },
    h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
  })(document);<|endoftext|>