<commit_before>var _errors = [];

(function() {
    window.onerror = function() {
        _errors.push(arguments);
    };

    var logError = function() {
        var newScript = document.createElement("script"),
            firstScript = document.getElementsByTagName("script")[0];

        newScript.src = "logger.js";
        newScript.async = true;
        firstScript.parentNode.insertBefore(newScript, firstScript)
    };

    window.addEventListener
        ? window.addEventListener("load", logError, false)
        : window.attachEvent("onload", logError)

    window.grabber = {

        fakeMode: false,

        fake: function(n) {
            console.log('Generating ', n, ' fake errors');
            this.fakeMode = true;

            var i = 0,
                err = [];

            if (!n) {
                n = 10; // default
            }
            for (i = 0; i < n; i++) {
                err = [
                    chance.sentence(),
                    'http://' + chance.domain() + '/' + chance.word() + '.html',
                    chance.integer({min: 1, max: 500}),
                    chance.integer({min: 1, max: 50})
                ];
                _errors.push(err);
            }

        }
    }
})();
<commit_msg>trivial style<commit_after>var _errors = [];

(function() {
    window.onerror = function() {
        _errors.push(arguments);
    };

    var logError = function() {
        var newScript = document.createElement("script"),
            firstScript = document.getElementsByTagName("script")[0];

        newScript.src = "logger.js";
        newScript.async = true;
        firstScript.parentNode.insertBefore(newScript, firstScript)
    };

    window.addEventListener
        ? window.addEventListener("load", logError, false)
        : window.attachEvent("onload", logError);

    window.grabber = {

        fakeMode: false,

        fake: function(n) {
            console.log('Generating ', n, ' fake errors');
            this.fakeMode = true;

            var i = 0,
                err = [];

            if (!n) {
                n = 10; // default
            }
            for (i = 0; i < n; i++) {
                err = [
                    chance.sentence(),
                    'http://' + chance.domain() + '/' + chance.word() + '.html',
                    chance.integer({min: 1, max: 500}),
                    chance.integer({min: 1, max: 50})
                ];
                _errors.push(err);
            }

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


<commit_before>import "@webcomponents/custom-elements";

import Keyboard from "../input/Keyboard.js";
import GUIInput from "./GUIInput.js";

let staticGUI;

// STYLES

let style = document.createElement("style");
document.head.appendChild(style);
style.sheet.insertRule(`
  dlib-gui {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 200px;
    padding: 5px;
    color: white;
    font-family: monospace;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui dlib-guiinput {
    margin: 5px 0;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui details details {
    margin-left: 10px;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui details summary {
    cursor: pointer;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui details summary:focus {
    outline: none;
  }
`, 0);

// UTILS

function componentToHex(c) {
  let hex = c.toString(16);
  return hex.length == 1 ? "0" + hex : hex;
}

function rgbToHex(r, g, b) {
  return "#" + componentToHex(r * 255) + componentToHex(g * 255) + componentToHex(b * 255);
}

function hexToRgb(hex) {
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16) / 255,
    g: parseInt(result[2], 16) / 255,
    b: parseInt(result[3], 16) / 255
  } : null;
}

function colorFromHex(color, hex) {
  if (typeof color === "string") {
    return hex;
  }

  let colorValue = hexToRgb(hex);

  if (color.r !== undefined) {
    Object.assign(color, colorValue);
  } else if (color.x !== undefined) {
    [color.x, color.y, color.z] = [colorValue.r, colorValue.g, colorValue.b];
  } else {
    [color[0], color[1], color[2]] = [colorValue.r, colorValue.g, colorValue.b];
  }

  return color;
}

function colorToHex(color) {
  if (typeof color === "string") {
    return color;
  }
  return rgbToHex(
    color.r !== undefined ? color.r : color.x !== undefined ? color.x : color[0],
    color.g !== undefined ? color.g : color.y !== undefined ? color.y : color[1],
    color.b !== undefined ? color.b : color.z !== undefined ? color.z : color[2]
  );
}

function normalizeString(string) {
  return `${string.toLowerCase().replace(/[^\w-]/g, "")}`;
}

function urlHashRegExpFromKey(key) {
  return new RegExp(`([#&]gui/${key}=)([^=&#?]*)`, "g");
}

// GUI

const GUI_REG_EXP = /([#&]gui=)((%7B|{).*(%7D|}))([&?]*)/;

let DATA = {};
(function() {
  let matches = GUI_REG_EXP.exec(window.location.hash);
  if (matches) {
    let string = matches[2];
    string = string.replace(/%7B/g, "{");
    string = string.replace(/%7D/g, "}");
    string = string.replace(/%22/g, "\"");
    window.location.hash = window.location.hash.replace(GUI_REG_EXP, `$1${string}$5`);
    DATA = JSON.parse(string);
  }
})();

export default class GUI extends HTMLElement {
  static add(...params) {
    if (!staticGUI.parentNode) {
      document.body.appendChild(staticGUI);
    }
    return staticGUI.add(...params);
  }

  static get element() {
    return staticGUI;
  }

  static set visible(value) {
    staticGUI.visible = value;
  }

  static get visible() {
    return staticGUI.visible;
  }

  static set open(value) {
    staticGUI.open = value;
  }

  static get open() {
    return staticGUI.open;
  }

  constructor() {
    super();

    this._groups = new Map();
    this._inputs = [];

    this._container = document.createElement("details");
    this._container.innerHTML = "GUI";
    this.open = true;
  }

  set visible(value) {
    this.style.visibility = value ? "visible" : "hidden";
  }

  get visible() {
    return this.style.visibility === "visible";
  }

  update() {
    for (let input of this._inputs) {
      input.update();
    }
  }

  set open(value) {
    this._container.open = value;
  }

  get open() {
    return this._container.open;
  }

  add(object, key, {type, label = key, group = "", reload = false, onChange = () => {
      }, options, max, min, step} = {}) {

    type = type || (options ? "select" : "");

    if (!type) {
      switch (typeof object[key]) {
        case "boolean":
          type = "checkbox";
          break;
        case "string":
          type = "text";
          break;
        case "function":
          type = "button";
          break;
        default:
          type = typeof object[key];
      }
    }

    let labelKey = normalizeString(label);
    let groupKey = normalizeString(group);
    const SAVED_VALUE = groupKey && DATA[groupKey] ? DATA[groupKey][labelKey] : DATA[labelKey];
    if (type === "color" && SAVED_VALUE) {
      object[key] = colorFromHex(object[key], SAVED_VALUE);
    }
    let value = SAVED_VALUE !== undefined ? SAVED_VALUE : (type === "color" ? colorToHex(object[key]) : object[key]);

    if (!this._container.parentNode) {
      this.appendChild(this._container);
    }
    let container = this._container;
    if(groupKey) {
      container = this._groups.get(groupKey);
      if(!container) {
        container = document.createElement("details");
        container.innerHTML = `<summary>${group}</summary>`;
        this._groups.set(groupKey, container);
        this._container.appendChild(container);
      }
    }
    let input = document.createElement("dlib-guiinput");
    input.object = type === "color" ? {
      value: "#000000"
    } : object;
    input.key = type === "color" ? "value" : key;
    input.label = label;
    input.value = value;
    if (min) {
      input.min = min;
    }
    if (max) {
      input.max = max;
    }
    if (step) {
      input.step = step;
    }
    if (options) {
      input.options = options;
    }
    input.type = type;
    container.appendChild(input);

    const reloadWindow = () => {
      if (!reload) {
        return;
      }

      if (Keyboard.hasKeyDown(Keyboard.SHIFT)) {
        Keyboard.onKeyUp.addOnce(() => {
          window.location.reload();
        }, this);
      } else {
        window.location.reload();
      }
    }

    if (type === "button") {
      input.addEventListener("click", reloadWindow);
    } else {
      if (type !== "color" && type !== "text") {
        input.addEventListener("input", () => {
          onChange(input.value);
        });
      }

      let timeoutId = -1;
      input.addEventListener("change", () => {
        let containerData = groupKey ? DATA[groupKey] : DATA;
        if (!containerData) {
          containerData = DATA[groupKey] = {};
        }
        containerData[labelKey] = input.value;

        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
          if (GUI_REG_EXP.test(window.location.hash)) {
            window.location.hash = window.location.hash.replace(GUI_REG_EXP, `$1${JSON.stringify(DATA)}$5`);
          } else {
            let prefix = window.location.hash ? "&" : "#";
            window.location.hash += `${prefix}gui=${JSON.stringify(DATA)}`;
          }
        }, 100);

        if (type === "color") {
          onChange(colorFromHex(object[key], input.value));
        } else if (type === "text") {
          onChange(input.value);
        }

        reloadWindow();
      });
    }

    onChange(object[key]);

    this._inputs.push(input);

    return input;
  }
}

window.customElements.define("dlib-gui", GUI);
staticGUI = document.createElement("dlib-gui");
<commit_msg>make GUI scrollable<commit_after>import "@webcomponents/custom-elements";

import Keyboard from "../input/Keyboard.js";
import GUIInput from "./GUIInput.js";

let staticGUI;

// STYLES

let style = document.createElement("style");
document.head.appendChild(style);
style.sheet.insertRule(`
  dlib-gui {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    width: 200px;
    padding: 5px;
    color: white;
    font-family: monospace;
    max-height: 100%;
    overflow: scroll;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui dlib-guiinput {
    margin: 5px 0;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui details details {
    margin-left: 10px;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui details summary {
    cursor: pointer;
  }
`, 0);
style.sheet.insertRule(`
  dlib-gui details summary:focus {
    outline: none;
  }
`, 0);

// UTILS

function componentToHex(c) {
  let hex = c.toString(16);
  return hex.length == 1 ? "0" + hex : hex;
}

function rgbToHex(r, g, b) {
  return "#" + componentToHex(r * 255) + componentToHex(g * 255) + componentToHex(b * 255);
}

function hexToRgb(hex) {
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  return result ? {
    r: parseInt(result[1], 16) / 255,
    g: parseInt(result[2], 16) / 255,
    b: parseInt(result[3], 16) / 255
  } : null;
}

function colorFromHex(color, hex) {
  if (typeof color === "string") {
    return hex;
  }

  let colorValue = hexToRgb(hex);

  if (color.r !== undefined) {
    Object.assign(color, colorValue);
  } else if (color.x !== undefined) {
    [color.x, color.y, color.z] = [colorValue.r, colorValue.g, colorValue.b];
  } else {
    [color[0], color[1], color[2]] = [colorValue.r, colorValue.g, colorValue.b];
  }

  return color;
}

function colorToHex(color) {
  if (typeof color === "string") {
    return color;
  }
  return rgbToHex(
    color.r !== undefined ? color.r : color.x !== undefined ? color.x : color[0],
    color.g !== undefined ? color.g : color.y !== undefined ? color.y : color[1],
    color.b !== undefined ? color.b : color.z !== undefined ? color.z : color[2]
  );
}

function normalizeString(string) {
  return `${string.toLowerCase().replace(/[^\w-]/g, "")}`;
}

function urlHashRegExpFromKey(key) {
  return new RegExp(`([#&]gui/${key}=)([^=&#?]*)`, "g");
}

// GUI

const GUI_REG_EXP = /([#&]gui=)((%7B|{).*(%7D|}))([&?]*)/;

let DATA = {};
(function() {
  let matches = GUI_REG_EXP.exec(window.location.hash);
  if (matches) {
    let string = matches[2];
    string = string.replace(/%7B/g, "{");
    string = string.replace(/%7D/g, "}");
    string = string.replace(/%22/g, "\"");
    window.location.hash = window.location.hash.replace(GUI_REG_EXP, `$1${string}$5`);
    DATA = JSON.parse(string);
  }
})();

export default class GUI extends HTMLElement {
  static add(...params) {
    if (!staticGUI.parentNode) {
      document.body.appendChild(staticGUI);
    }
    return staticGUI.add(...params);
  }

  static get element() {
    return staticGUI;
  }

  static set visible(value) {
    staticGUI.visible = value;
  }

  static get visible() {
    return staticGUI.visible;
  }

  static set open(value) {
    staticGUI.open = value;
  }

  static get open() {
    return staticGUI.open;
  }

  constructor() {
    super();

    this._groups = new Map();
    this._inputs = [];

    this._container = document.createElement("details");
    this._container.innerHTML = "GUI";
    this.open = true;
  }

  set visible(value) {
    this.style.visibility = value ? "visible" : "hidden";
  }

  get visible() {
    return this.style.visibility === "visible";
  }

  update() {
    for (let input of this._inputs) {
      input.update();
    }
  }

  set open(value) {
    this._container.open = value;
  }

  get open() {
    return this._container.open;
  }

  add(object, key, {type, label = key, group = "", reload = false, onChange = () => {
      }, options, max, min, step} = {}) {

    type = type || (options ? "select" : "");

    if (!type) {
      switch (typeof object[key]) {
        case "boolean":
          type = "checkbox";
          break;
        case "string":
          type = "text";
          break;
        case "function":
          type = "button";
          break;
        default:
          type = typeof object[key];
      }
    }

    let labelKey = normalizeString(label);
    let groupKey = normalizeString(group);
    const SAVED_VALUE = groupKey && DATA[groupKey] ? DATA[groupKey][labelKey] : DATA[labelKey];
    if (type === "color" && SAVED_VALUE) {
      object[key] = colorFromHex(object[key], SAVED_VALUE);
    }
    let value = SAVED_VALUE !== undefined ? SAVED_VALUE : (type === "color" ? colorToHex(object[key]) : object[key]);

    if (!this._container.parentNode) {
      this.appendChild(this._container);
    }
    let container = this._container;
    if(groupKey) {
      container = this._groups.get(groupKey);
      if(!container) {
        container = document.createElement("details");
        container.innerHTML = `<summary>${group}</summary>`;
        this._groups.set(groupKey, container);
        this._container.appendChild(container);
      }
    }
    let input = document.createElement("dlib-guiinput");
    input.object = type === "color" ? {
      value: "#000000"
    } : object;
    input.key = type === "color" ? "value" : key;
    input.label = label;
    input.value = value;
    if (min) {
      input.min = min;
    }
    if (max) {
      input.max = max;
    }
    if (step) {
      input.step = step;
    }
    if (options) {
      input.options = options;
    }
    input.type = type;
    container.appendChild(input);

    const reloadWindow = () => {
      if (!reload) {
        return;
      }

      if (Keyboard.hasKeyDown(Keyboard.SHIFT)) {
        Keyboard.onKeyUp.addOnce(() => {
          window.location.reload();
        }, this);
      } else {
        window.location.reload();
      }
    }

    if (type === "button") {
      input.addEventListener("click", reloadWindow);
    } else {
      if (type !== "color" && type !== "text") {
        input.addEventListener("input", () => {
          onChange(input.value);
        });
      }

      let timeoutId = -1;
      input.addEventListener("change", () => {
        let containerData = groupKey ? DATA[groupKey] : DATA;
        if (!containerData) {
          containerData = DATA[groupKey] = {};
        }
        containerData[labelKey] = input.value;

        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
          if (GUI_REG_EXP.test(window.location.hash)) {
            window.location.hash = window.location.hash.replace(GUI_REG_EXP, `$1${JSON.stringify(DATA)}$5`);
          } else {
            let prefix = window.location.hash ? "&" : "#";
            window.location.hash += `${prefix}gui=${JSON.stringify(DATA)}`;
          }
        }, 100);

        if (type === "color") {
          onChange(colorFromHex(object[key], input.value));
        } else if (type === "text") {
          onChange(input.value);
        }

        reloadWindow();
      });
    }

    onChange(object[key]);

    this._inputs.push(input);

    return input;
  }
}

window.customElements.define("dlib-gui", GUI);
staticGUI = document.createElement("dlib-gui");
<|endoftext|>


<commit_before>import { fp64ify } from 'deck.gl/dist/lib/utils'
import { Layer, COORDINATE_SYSTEM } from 'deck.gl'
// import {enable64bitSupport} from 'deck.gl/lib/utils/fp64.js'
import { GL, Framebuffer, Texture2D, Model, Geometry } from 'luma.gl'

import vs from './heatmapFromPoints-layer-vertex.glsl'
// import vs64 from './experimentalshader-layer-vertex-64.glsl'
import fs from './heatmapFromPoints-layer-fragment.glsl'
import fsScreen from './grayscaleToColor-fragment.glsl'
import vsScreen from './screenQuad-vertex.glsl'

const DEFAULT_COLOR = [0, 0, 0, 255]

const defaultProps = {
  radiusScale: 1,
  fillOpacity: 1.0,
  height: 1.0,
  fp64: false,
  getPosition: x => x.position,
  getRadius: x => x.radius || 1,
  getColor: x => x.color || DEFAULT_COLOR
}

export default class HeatmapFromPointsShader extends Layer {
  getShaders (id) {
    const { shaderCache } = this.context
    return { vs, fs, modules: ['project'], shaderCache }
  }

  getShaders2 (id) {
    const { shaderCache } = this.context
    return { vs: vsScreen, fs: fsScreen, modules: ['project'], shaderCache }
  }

  initializeState () {
    const { gl } = this.context
    const heatTexture = new Texture2D(gl, {
      width: gl.canvas.width,
      height: gl.canvas.height,
      format: GL.RGBA,
      parameters: {
        [GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
        [GL.TEXTURE_MIN_FILTER]: GL.NEAREST,
      },
      pixelStore: {
        [GL.UNPACK_FLIP_Y_WEBGL]: true
      },
      mipmaps: false
    })

    var fbHeat = new Framebuffer(gl, {
      depth: false,
//      clearColor: [255, 0, 0, 1],
  //    clearDepth: 0,
	    })
    //  fbHeat.initialize({ bytes: gl.canvas.width * gl.canvas.height * 4 });
    //  fbHeat.clear();
    //   fbHeat.attach([heatTexture]);
    //   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, heatTexture);

    /* eslint-disable max-len */
    /* deprecated props check */
    this._checkRemovedProp('radius', 'radiusScale')

    this.state.attributeManager.addInstanced({
      instancePositions: {
        size: 3,
        accessor: 'getPosition',
        update: this.calculateInstancePositions
      },
      instanceRadius: {
        size: 1,
        accessor: 'getRadius',
        defaultValue: 1,
        update: this.calculateInstanceRadius
      }
    })
    /* eslint-enable max-len */

    const rampTexture = new Texture2D(gl, {
      width: 256,
      height: 1,
      format: GL.RGBA,
      data: new Uint8Array(this.props.colorRamp),
      parameters: {
        [GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
        [GL.TEXTURE_MIN_FILTER]: GL.NEAREST
      },
      pixelStore: {
        [GL.UNPACK_FLIP_Y_WEBGL]: true
      },
      mipmaps: true
    })
    //   rampTexture.bind(0);
    this.setState({
      model: this._getModel(gl),
      model2: this._getModel2(gl),
      fbHeat,
      rampTexture
    })
  }

  updateAttribute ({ props, oldProps, changeFlags }) {
    if (props.fp64 !== oldProps.fp64) {
      const { attributeManager } = this.state
      attributeManager.invalidateAll()

      if (props.fp64 && props.projectionMode === COORDINATE_SYSTEM.LNGLAT) {
        attributeManager.addInstanced({
          instancePositions64xyLow: {
            size: 2,
            accessor: 'getPosition',
            update: this.calculateInstancePositions64xyLow
          }
        })
      } else {
        attributeManager.remove(['instancePositions64xyLow'])
      }
    }
  }

  updateState ({ props, oldProps, changeFlags }) {
    super.updateState({ props, oldProps, changeFlags })
    if (props.fp64 !== oldProps.fp64) {
      const { gl } = this.context
      this.setState({
        model: this._getModel(gl),
        model2: this._getModel2(gl)
      })
    }
    this.updateAttribute({ props, oldProps, changeFlags })
  }

  draw ({ uniforms }) {
    const gl = this.state.model.gl
    var fbHeat = this.state.fbHeat

    const {width, height} = gl.canvas
    fbHeat.resize({width, height});
    fbHeat.bind(gl.FRAMEBUFFER);
    gl.clear(gl.COLOR_BUFFER_BIT);
    const { radiusScale, fillOpacity } = this.props
    const args = Object.assign({}, uniforms, {
      radiusScale,
      fillOpacity,
      height: this.props.height
    })

    gl.blendFunc(gl.ONE, gl.ONE)
    //   window.luma.log.priority = 4;
    this.state.model.draw({
      framebuffer: fbHeat,
      uniforms: args
    })

    gl.blendFuncSeparate(
      gl.SRC_ALPHA,
      gl.ONE_MINUS_SRC_ALPHA,
      gl.ONE,
      gl.ONE_MINUS_SRC_ALPHA
);

    this.state.model2.draw({
      framebuffer: null,
      uniforms: {
        colorRamp: this.state.rampTexture,
        heatTexture: fbHeat.texture,
        fillOpacity: this.props.fillOpacity,
        uRes: [gl.canvas.width, gl.canvas.height]
      }
    })
  }

  _getModel (gl) {
    // a square that minimally cover the unit circle
    const positions = [-1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0]

    return new Model(
      gl,
      Object.assign(this.getShaders(), {
        id: this.props.id,
        geometry: new Geometry({
          drawMode: GL.TRIANGLE_FAN,
          positions: new Float32Array(positions)
        }),
        isInstanced: true,
        shaderCache: this.context.shaderCache
      })
    )
  }

  _getModel2 (gl) {
    // a square that minimally cover the unit circle
    const positions = [-1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0]

    return new Model(
      gl,
      Object.assign(this.getShaders2(), {
        id: this.props.id,
        geometry: new Geometry({
          drawMode: GL.TRIANGLE_FAN,
          positions: new Float32Array(positions)
        }),
        isInstanced: false,
        shaderCache: this.context.shaderCache
      })
    )
  }

  calculateInstancePositions (attribute) {
    const { data, getPosition } = this.props
    const { value } = attribute
    let i = 0
    for (const point of data) {
      const position = getPosition(point)
      value[i++] = position[0]
      value[i++] = position[1]
      value[i++] = position[2] || 0
    }
  }

  calculateInstancePositions64xyLow (attribute) {
    const { data, getPosition } = this.props
    const { value } = attribute
    let i = 0
    for (const point of data) {
      const position = getPosition(point)
      value[i++] = fp64ify(position[0])[1]
      value[i++] = fp64ify(position[1])[1]
    }
  }

  calculateInstanceRadius (attribute) {
    const { data, getRadius } = this.props
    const { value } = attribute
    let i = 0
    for (const point of data) {
      const radius = getRadius(point)
      value[i++] = isNaN(radius) ? 1 : radius
    }
  }
}

HeatmapFromPointsShader.layerName = 'HeatmapFromPointsShader'
HeatmapFromPointsShader.defaultProps = defaultProps
<commit_msg>Cleanup<commit_after>import { fp64ify } from 'deck.gl/dist/lib/utils'
import { Layer, COORDINATE_SYSTEM } from 'deck.gl'
// import {enable64bitSupport} from 'deck.gl/lib/utils/fp64.js'
import { GL, Framebuffer, Texture2D, Model, Geometry } from 'luma.gl'

import vs from './heatmapFromPoints-layer-vertex.glsl'
// import vs64 from './experimentalshader-layer-vertex-64.glsl'
import fs from './heatmapFromPoints-layer-fragment.glsl'
import fsScreen from './grayscaleToColor-fragment.glsl'
import vsScreen from './screenQuad-vertex.glsl'

const DEFAULT_COLOR = [0, 0, 0, 255]

const defaultProps = {
  radiusScale: 1,
  fillOpacity: 1.0,
  height: 1.0,
  fp64: false,
  getPosition: x => x.position,
  getRadius: x => x.radius || 1,
  getColor: x => x.color || DEFAULT_COLOR
}

export default class HeatmapFromPointsShader extends Layer {
  getShaders (id) {
    const { shaderCache } = this.context
    return { vs, fs, modules: ['project'], shaderCache }
  }

  getShaders2 (id) {
    const { shaderCache } = this.context
    return { vs: vsScreen, fs: fsScreen, modules: ['project'], shaderCache }
  }

  initializeState () {
    const { gl } = this.context
    const heatTexture = new Texture2D(gl, {
      width: gl.canvas.width,
      height: gl.canvas.height,
      format: GL.RGBA,
      parameters: {
        [GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
        [GL.TEXTURE_MIN_FILTER]: GL.NEAREST,
      },
      pixelStore: {
        [GL.UNPACK_FLIP_Y_WEBGL]: true
      },
      mipmaps: false
    })

    var fbHeat = new Framebuffer(gl, {depth: false})

    /* eslint-disable max-len */
    /* deprecated props check */
    this._checkRemovedProp('radius', 'radiusScale')

    this.state.attributeManager.addInstanced({
      instancePositions: {
        size: 3,
        accessor: 'getPosition',
        update: this.calculateInstancePositions
      },
      instanceRadius: {
        size: 1,
        accessor: 'getRadius',
        defaultValue: 1,
        update: this.calculateInstanceRadius
      }
    })
    /* eslint-enable max-len */

    const rampTexture = new Texture2D(gl, {
      width: 256,
      height: 1,
      format: GL.RGBA,
      data: new Uint8Array(this.props.colorRamp),
      parameters: {
        [GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
        [GL.TEXTURE_MIN_FILTER]: GL.NEAREST
      },
      mipmaps: false
    })
    //   rampTexture.bind(0);
    this.setState({
      model: this._getModel(gl),
      model2: this._getModel2(gl),
      fbHeat,
      rampTexture
    })
  }

  updateAttribute ({ props, oldProps, changeFlags }) {
    if (props.fp64 !== oldProps.fp64) {
      const { attributeManager } = this.state
      attributeManager.invalidateAll()

      if (props.fp64 && props.projectionMode === COORDINATE_SYSTEM.LNGLAT) {
        attributeManager.addInstanced({
          instancePositions64xyLow: {
            size: 2,
            accessor: 'getPosition',
            update: this.calculateInstancePositions64xyLow
          }
        })
      } else {
        attributeManager.remove(['instancePositions64xyLow'])
      }
    }
  }

  updateState ({ props, oldProps, changeFlags }) {
    super.updateState({ props, oldProps, changeFlags })
    if (props.fp64 !== oldProps.fp64) {
      const { gl } = this.context
      this.setState({
        model: this._getModel(gl),
        model2: this._getModel2(gl)
      })
    }
    this.updateAttribute({ props, oldProps, changeFlags })
  }

  draw ({ uniforms }) {
    const gl = this.state.model.gl
    var fbHeat = this.state.fbHeat

    const {width, height} = gl.canvas
    fbHeat.resize({width, height});
    fbHeat.bind(gl.FRAMEBUFFER);
    gl.clear(gl.COLOR_BUFFER_BIT);
    const { radiusScale, fillOpacity } = this.props
    const args = Object.assign({}, uniforms, {
      radiusScale,
      fillOpacity,
      height: this.props.height
    })

    gl.blendFunc(gl.ONE, gl.ONE)
    //   window.luma.log.priority = 4;
    this.state.model.draw({
      framebuffer: fbHeat,
      uniforms: args
    })

    gl.blendFuncSeparate(
      gl.SRC_ALPHA,
      gl.ONE_MINUS_SRC_ALPHA,
      gl.ONE,
      gl.ONE_MINUS_SRC_ALPHA
);

    this.state.model2.draw({
      framebuffer: null,
      uniforms: {
        colorRamp: this.state.rampTexture,
        heatTexture: fbHeat.texture,
        fillOpacity: this.props.fillOpacity,
        uRes: [gl.canvas.width, gl.canvas.height]
      }
    })
  }

  _getModel (gl) {
    // a square that minimally cover the unit circle
    const positions = [-1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0]

    return new Model(
      gl,
      Object.assign(this.getShaders(), {
        id: this.props.id,
        geometry: new Geometry({
          drawMode: GL.TRIANGLE_FAN,
          positions: new Float32Array(positions)
        }),
        isInstanced: true,
        shaderCache: this.context.shaderCache
      })
    )
  }

  _getModel2 (gl) {
    // a square that minimally cover the unit circle
    const positions = [-1, -1, 0, -1, 1, 0, 1, 1, 0, 1, -1, 0]

    return new Model(
      gl,
      Object.assign(this.getShaders2(), {
        id: this.props.id,
        geometry: new Geometry({
          drawMode: GL.TRIANGLE_FAN,
          positions: new Float32Array(positions)
        }),
        isInstanced: false,
        shaderCache: this.context.shaderCache
      })
    )
  }

  calculateInstancePositions (attribute) {
    const { data, getPosition } = this.props
    const { value } = attribute
    let i = 0
    for (const point of data) {
      const position = getPosition(point)
      value[i++] = position[0]
      value[i++] = position[1]
      value[i++] = position[2] || 0
    }
  }

  calculateInstancePositions64xyLow (attribute) {
    const { data, getPosition } = this.props
    const { value } = attribute
    let i = 0
    for (const point of data) {
      const position = getPosition(point)
      value[i++] = fp64ify(position[0])[1]
      value[i++] = fp64ify(position[1])[1]
    }
  }

  calculateInstanceRadius (attribute) {
    const { data, getRadius } = this.props
    const { value } = attribute
    let i = 0
    for (const point of data) {
      const radius = getRadius(point)
      value[i++] = isNaN(radius) ? 1 : radius
    }
  }
}

HeatmapFromPointsShader.layerName = 'HeatmapFromPointsShader'
HeatmapFromPointsShader.defaultProps = defaultProps
<|endoftext|>


<commit_before>'use strict';

var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

module.exports.saveEmailStatus = (event, context, callback) => {

	var addressList = [];

  var message = JSON.parse(event.Records[0].Sns.Message);
  console.log("message1: ", message);
  var notificationType = message.notificationType;
  console.log("notificationType",notificationType);
  var delivery = message.delivery;
  console.log("delivery", delivery);
  var mail = message.mail;
  console.log("mail", mail);
  var dest = mail.destination;
  console.log("dest", dest);

	if (dest !== null) {
		dest.forEach((addr) => {
			addressList.push(addr);
		});

		var status;
		if (message.mail.notificationType === "Delivery") {
			status = "Delivered";
		} else if (message.mail.bounce) {
			if (message.mail.bounce.bounceSubtype === "General") {
				status = "No domain";
			} else {
				status = "Bad email address";
			}
		} else {
			status = "Complaint";
		}

		var messageId = message.mail.messageId;

		var params = {
			"Key": {
				"MessageId": {
					S: messageId
				}
			},
			"ReturnValues":"NONE",
			"ExpressionAttributeNames": {
				"#AL": "Addresses",
				"#S":"Status"
			},
			"ExpressionAttributeValues": {
				":al": {
					"SS":addressList
				},
				":s": {
					"S":status
				}
			},
			"UpdateExpression": "SET #AL = :al, #S = :s",
  			"TableName": "SentEmailStatus"
		};

		postToDynamoDB(params).then((res) => {
			console.log("resForPost", res);
		});
	} else {
		console.log("Destination was null ");
	}
};

function postToDynamoDB(params) {
	return new Promise((resolve, reject) => {
		dynamodb.updateItem(params, (err, data) => {
			if (err) {
				console.log(err);
				console.log("These params were rejected: ", params);
				reject(err);
			} else {
				resolve(data);
			}
		})
	});
}
<commit_msg>Correct location of notification type.<commit_after>'use strict';

var AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'});

module.exports.saveEmailStatus = (event, context, callback) => {

	var addressList = [];

  var message = JSON.parse(event.Records[0].Sns.Message);
  console.log("message1: ", message);
  var notificationType = message.notificationType;
  console.log("notificationType",notificationType);
  var delivery = message.delivery;
  console.log("delivery", delivery);
  var mail = message.mail;
  console.log("mail", mail);
  var dest = mail.destination;
  console.log("dest", dest);

	if (dest !== null) {
		dest.forEach((addr) => {
			addressList.push(addr);
		});

		var status;
		if (message.notificationType === "Delivery") {
			status = "Delivered";
		} else if (message.mail.bounce) {
			if (message.mail.bounce.bounceSubtype === "General") {
				status = "No domain";
			} else {
				status = "Bad email address";
			}
		} else {
			status = "Complaint";
		}

		var messageId = message.mail.messageId;

		var params = {
			"Key": {
				"MessageId": {
					S: messageId
				}
			},
			"ReturnValues":"NONE",
			"ExpressionAttributeNames": {
				"#AL": "Addresses",
				"#S":"Status"
			},
			"ExpressionAttributeValues": {
				":al": {
					"SS":addressList
				},
				":s": {
					"S":status
				}
			},
			"UpdateExpression": "SET #AL = :al, #S = :s",
  			"TableName": "SentEmailStatus"
		};

		postToDynamoDB(params).then((res) => {
			console.log("resForPost", res);
		});
	} else {
		console.log("Destination was null ");
	}
};

function postToDynamoDB(params) {
	return new Promise((resolve, reject) => {
		dynamodb.updateItem(params, (err, data) => {
			if (err) {
				console.log(err);
				console.log("These params were rejected: ", params);
				reject(err);
			} else {
				resolve(data);
			}
		})
	});
}
<|endoftext|>


<commit_before>/*
 * haptics.js (https://github.com/EbookGlue/haptics.js)
 * Copyright (c) Shantanu Bala 2014
 * http://sbala.org/haptics.js
 * shantanu@sbala.org
 * Available under the MIT License.
 */

;

(function (global) {
    var Haptics = {},
        enabled,
        vibrate,
        currentRecording,
        log;

    Haptics.resolution = 10; // lower is sharper

    // a console.log wrapper for debugging
    log = function(){
        // store logs to an array for reference
        log.history = log.history || [];
        log.history.push(arguments);
        if(global.console){
            global.console.log(Array.prototype.slice.call(arguments));
        }
    };

    // check for navigator variables from different vendors
    enabled = navigatorVibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;

    function vibrate() {
        navigatorVibrate.apply(navigator, arguments);
    }

    enabled = !! enabled; // convert to boolean

    function executeSequence(durations, currentFunc, nextFunc) {
        nextFunc = nextFunc || currentFunc;
        var d = durations.shift();
        currentFunc(d);
        return window.setTimeout(function () {
            executeSequence(durations, nextFunc, currentFunc);
        }, d);
    }

    // expose a wrapped copy of 'vibrate' function
    if (enabled) {
        Haptics.vibrate = function (args) {
            vibrate(args);
            return false;
        };
    }
    else {
        Haptics.vibrate = function () {
            return false;
        };
    }

    // used for timeouts that 'accomplish nothing' in a pattern
    function emptyFunc() {
        // do nothing
    }

    // handle click/touch event
    function onRecord(e) {
        e.preventDefault();
        currentRecording.push(new Date());
    }
    // begin recording a sequence of taps/clicks
    function record() {
        currentRecording = [];
        window.addEventListener("touchstart". onRecord, false);
        window.addEventListener("touchend". onRecord, false);
        window.addEventListener("mousedown", onRecord, false);
        window.addEventListener("mouseup". onRecord, false);
    }
    // complete a recording of a sequence of taps/clicks
    function finish() {
        log(currentRecording);
        window.removeEventListener("touchstart". onRecord);
        window.removeEventListener("touchend". onRecord);
        window.removeEventListener("mousedown", onRecord);
        window.removeEventListener("mouseup". onRecord);

        if (currentRecording.length % 2 != 0)
            currentRecording.push(new Date());

        var vibrationPattern = [],
            i,
            j,
            len;

        for (i = 0; i < len; i += 2) {
            j = i + 1;
            if (! j < len)
                break;
            vibrationPattern.push(currentRecording[j] - currentRecording[i]);
        }

        return vibrationPattern;
    }

    // EFFECTS: Fade In
    function vibrateFadeIn(duration) {
        var pulses = [Haptics.resolution],
            len = duration / Haptics.resolution,
            resolution = Haptics.resolution,
            i;
        for (i = 1; i <= len; i += 1) {
            pulses.push(resolution);
            pulses.push(i * resolution);
        }
        pulses.reverse();
        vibrate(pulses);
    }

    function fadeIn(args) {
        if (typeof args == "number") {
            vibrateFadeIn(args);
        }
        else {
            executeSequence(args, vibrateFadeIn, emptyFunc);
        }
    }

    // EFFECTS: Fade Out
    function vibrateFadeOut(duration) {
        var pulses = [Haptics.resolution],
            len = duration / Haptics.resolution,
            resolution = Haptics.resolution,
            i;
        for (i = 1; i <= len; i += 1) {
            pulses.push(resolution);
            pulses.push(i * resolution);
        }
        vibrate(pulses);
    }

    function fadeOut(args) {
        if (typeof args == "number") {
            vibrateFadeOut(args);
        }
        else {
            executeSequence(args, vibrateFadeOut, emptyFunc);
        }
    }

    // EFFECTS: notification
    function vibrateNotification(duration) {
        var pause, dot, dash;
        pause = duration / 27;
        dot = 2*pause;
        dash = 3*pause;
        vibrate([dot, pause, dot, pause, dot, pause*2, dash, pause, dash, pause*2, dot, pause, dot, pause, dot]);
    }

    function notification(args) {
        if (typeof args == "number") {
            vibrateNotification(args);
        }
        else {
            executeSequence(args, vibrateNotification, emptyFunc);
        }
    }

    // EFFECTS: heartbeat
    function vibrateHeartbeat(duration) {
        var pause, dot, dash;
        dot = duration / 60;
        pause = dot * 2;
        dash = dot * 24;
        vibrate([dot, pause, dash, pause * 2, dash, pause * 2, dot]);
    }

    function heartbeat(args) {
        if (typeof args == "number") {
            vibrateHeartbeat(args);
        }
        else {
            executeSequence(args, vibrateHeartbeat, emptyFunc);
        }
    }

    // EFFECTS: heartbeat
    function vibrateClunk(duration) {
        var pause, dot, dash;
        dot = duration * 4 / 22;
        pause = dot * 2;
        dash = dot / 2 * 5;
        vibrate([dot, pause, dash]);
    }

    function clunk(args) {
        if (typeof args == "number") {
            vibrateClunk(args);
        }
        else {
            executeSequence(args, vibrateClunk, emptyFunc);
        }
    }

    // EFFECTS: PWM
    function vibratePWM(duration, on, off) {
        var pattern = [on];
        duration -= on;
        while (duration > 0) {
            duration -= off;
            duration -= on;
            pattern.push(off);
            pattern.push(on);
        }
        vibrate(pattern);
    }

    function pwm(args, on, off) {
        if (typeof args == "number") {
            vibratePWM(args, on, off);
        }
        else {
            function newVibratePWM(d) {
                vibratePWM(d, on, off);
            }
            executeSequence(args, newVibratePWM, emptyFunc);
        }
    }

    function pwmFactory(on, off) {
        return function (args) {
            pwm(args, on, off);
        }
    }

    // a way to quickly create/compose new tactile animations
    function patternFactory(funcs) {
        var i = 0,
            len = funcs.length;

        function newPattern(duration) {
            funcs[i](duration);
            i += 1;
            if (i == len) {
                i = 0;
            }
        }
        return function (args) {
            if (typeof args == "number") {
                newPattern(args);
            }
            else {
                executeSequence(args, newPattern, emptyFunc);
            }
        }
    }

    // expose local functions to global API
    Haptics.enabled = enabled;
    Haptics.record = record;
    Haptics.finish = finish;
    Haptics.fadeIn = fadeIn;
    Haptics.fadeOut = fadeOut;
    Haptics.notification = notification;
    Haptics.heartbeat = heartbeat;
    Haptics.clunk = clunk;
    Haptics.pwm = pwm;
    Haptics.pwmFactory = pwmFactory;
    Haptics.patternFactory = patternFactory;

    // set global object
    global.Haptics = Haptics;
})(this);
<commit_msg>fixed return value to indicate proper enablement<commit_after>/*
 * haptics.js (https://github.com/EbookGlue/haptics.js)
 * Copyright (c) Shantanu Bala 2014
 * http://sbala.org/haptics.js
 * shantanu@sbala.org
 * Available under the MIT License.
 */

;

(function (global) {
    var Haptics = {},
        enabled,
        vibrate,
        currentRecording,
        log;

    Haptics.resolution = 10; // lower is sharper

    // a console.log wrapper for debugging
    log = function(){
        // store logs to an array for reference
        log.history = log.history || [];
        log.history.push(arguments);
        if(global.console){
            global.console.log(Array.prototype.slice.call(arguments));
        }
    };

    // check for navigator variables from different vendors
    enabled = navigatorVibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;

    function vibrate() {
        navigatorVibrate.apply(navigator, arguments);
    }

    enabled = !! enabled; // convert to boolean

    function executeSequence(durations, currentFunc, nextFunc) {
        nextFunc = nextFunc || currentFunc;
        var d = durations.shift();
        currentFunc(d);
        return window.setTimeout(function () {
            executeSequence(durations, nextFunc, currentFunc);
        }, d);
    }

    // expose a wrapped copy of 'vibrate' function
    if (enabled) {
        Haptics.vibrate = function (args) {
            vibrate(args);
            return true;
        };
    }
    else {
        Haptics.vibrate = function () {
            return false;
        };
    }

    // used for timeouts that 'accomplish nothing' in a pattern
    function emptyFunc() {
        // do nothing
    }

    // handle click/touch event
    function onRecord(e) {
        e.preventDefault();
        currentRecording.push(new Date());
    }
    // begin recording a sequence of taps/clicks
    function record() {
        currentRecording = [];
        window.addEventListener("touchstart". onRecord, false);
        window.addEventListener("touchend". onRecord, false);
        window.addEventListener("mousedown", onRecord, false);
        window.addEventListener("mouseup". onRecord, false);
    }
    // complete a recording of a sequence of taps/clicks
    function finish() {
        log(currentRecording);
        window.removeEventListener("touchstart". onRecord);
        window.removeEventListener("touchend". onRecord);
        window.removeEventListener("mousedown", onRecord);
        window.removeEventListener("mouseup". onRecord);

        if (currentRecording.length % 2 != 0)
            currentRecording.push(new Date());

        var vibrationPattern = [],
            i,
            j,
            len;

        for (i = 0; i < len; i += 2) {
            j = i + 1;
            if (! j < len)
                break;
            vibrationPattern.push(currentRecording[j] - currentRecording[i]);
        }

        return vibrationPattern;
    }

    // EFFECTS: Fade In
    function vibrateFadeIn(duration) {
        var pulses = [Haptics.resolution],
            len = duration / Haptics.resolution,
            resolution = Haptics.resolution,
            i;
        for (i = 1; i <= len; i += 1) {
            pulses.push(resolution);
            pulses.push(i * resolution);
        }
        pulses.reverse();
        vibrate(pulses);
    }

    function fadeIn(args) {
        if (typeof args == "number") {
            vibrateFadeIn(args);
        }
        else {
            executeSequence(args, vibrateFadeIn, emptyFunc);
        }
    }

    // EFFECTS: Fade Out
    function vibrateFadeOut(duration) {
        var pulses = [Haptics.resolution],
            len = duration / Haptics.resolution,
            resolution = Haptics.resolution,
            i;
        for (i = 1; i <= len; i += 1) {
            pulses.push(resolution);
            pulses.push(i * resolution);
        }
        vibrate(pulses);
    }

    function fadeOut(args) {
        if (typeof args == "number") {
            vibrateFadeOut(args);
        }
        else {
            executeSequence(args, vibrateFadeOut, emptyFunc);
        }
    }

    // EFFECTS: notification
    function vibrateNotification(duration) {
        var pause, dot, dash;
        pause = duration / 27;
        dot = 2*pause;
        dash = 3*pause;
        vibrate([dot, pause, dot, pause, dot, pause*2, dash, pause, dash, pause*2, dot, pause, dot, pause, dot]);
    }

    function notification(args) {
        if (typeof args == "number") {
            vibrateNotification(args);
        }
        else {
            executeSequence(args, vibrateNotification, emptyFunc);
        }
    }

    // EFFECTS: heartbeat
    function vibrateHeartbeat(duration) {
        var pause, dot, dash;
        dot = duration / 60;
        pause = dot * 2;
        dash = dot * 24;
        vibrate([dot, pause, dash, pause * 2, dash, pause * 2, dot]);
    }

    function heartbeat(args) {
        if (typeof args == "number") {
            vibrateHeartbeat(args);
        }
        else {
            executeSequence(args, vibrateHeartbeat, emptyFunc);
        }
    }

    // EFFECTS: heartbeat
    function vibrateClunk(duration) {
        var pause, dot, dash;
        dot = duration * 4 / 22;
        pause = dot * 2;
        dash = dot / 2 * 5;
        vibrate([dot, pause, dash]);
    }

    function clunk(args) {
        if (typeof args == "number") {
            vibrateClunk(args);
        }
        else {
            executeSequence(args, vibrateClunk, emptyFunc);
        }
    }

    // EFFECTS: PWM
    function vibratePWM(duration, on, off) {
        var pattern = [on];
        duration -= on;
        while (duration > 0) {
            duration -= off;
            duration -= on;
            pattern.push(off);
            pattern.push(on);
        }
        vibrate(pattern);
    }

    function pwm(args, on, off) {
        if (typeof args == "number") {
            vibratePWM(args, on, off);
        }
        else {
            function newVibratePWM(d) {
                vibratePWM(d, on, off);
            }
            executeSequence(args, newVibratePWM, emptyFunc);
        }
    }

    function pwmFactory(on, off) {
        return function (args) {
            pwm(args, on, off);
        }
    }

    // a way to quickly create/compose new tactile animations
    function patternFactory(funcs) {
        var i = 0,
            len = funcs.length;

        function newPattern(duration) {
            funcs[i](duration);
            i += 1;
            if (i == len) {
                i = 0;
            }
        }
        return function (args) {
            if (typeof args == "number") {
                newPattern(args);
            }
            else {
                executeSequence(args, newPattern, emptyFunc);
            }
        }
    }

    // expose local functions to global API
    Haptics.enabled = enabled;
    Haptics.record = record;
    Haptics.finish = finish;
    Haptics.fadeIn = fadeIn;
    Haptics.fadeOut = fadeOut;
    Haptics.notification = notification;
    Haptics.heartbeat = heartbeat;
    Haptics.clunk = clunk;
    Haptics.pwm = pwm;
    Haptics.pwmFactory = pwmFactory;
    Haptics.patternFactory = patternFactory;

    // set global object
    global.Haptics = Haptics;
})(this);
<|endoftext|>


<commit_before>/*  HashNav is ...
    It was inspired by https://github.com/ccoenraets/PageSlider

    @note: this library depends on jquery core.

    General Usage:
        var hashnav = new HashNav(container_id, options);

    Example use:
        var hashnav = new HashNav('container');
        hashnav.add_route("/foo/", {top_level_tab_index: 0}, function(a){ return '
Foo
'; };
        hashnav.add_route("/foo/(.*)/bar", function(a){ return '
Foo: ' + a + '
'; })
        hashnav.add_route("/foo/(.*)/bar", function(a){ return '
Bar: ' + a + '
'; })
        hashnav.add_route("/foo/(.*)/baz", function(a){ return '
Baz: ' + a + '
'; })

    Options:
     - allow_reloads -- regenerate same page twice in a row; this can also be
        specified per route; possible use case is if route involves querying
        of possibly chnging data from server
     - always_transition_top_level_pages_from_center -- Don't use left/right
        transition effect when going from one top level tab
     - after_render -- callback to be executed after rendering any route
        (called before any route-specific after-render callback)
*/

function HashNav(container_id, options) {
    options = options || {};

    var history = [];
    var routes = [];

    var path_param_matcher = /:[^/]+/g;

    /** Public Interface **/

    /*  add_route: associates routes matching a pattern with a content generator.
        @todo: switch 'generator' and 'options' args and support missing options

        Options:
         - allow_reloads -- same meaning as global option of same name, except
            specific to this route.
         - top_level_tab_index -- use for animating left/right transition between
            top level tabs
         - after_render -- callback to be executed after rendering this route
            (called after any global after-render callback)
    */
    this.add_route = function(pattern, route_options, generator) {
        if (typeof route_options == 'function') {
            generator = route_options;
            route_options = {};
        } else {
            route_options = route_options || {};
        }

        //pattern = pattern.replace(/\/*$/, ''); /* so that we match with or with trailing slash */

        pattern = pattern.replace(path_param_matcher, '([^/]+)');

        var r = {
            matcher: RegExp("^" + pattern + "$"),
            generator: generator
        };
        if (typeof route_options.top_level_tab_index != 'undefined') {
            r.top_level_tab_index = route_options.top_level_tab_index;
        }
        if (typeof route_options.after_render != 'undefined') {
            r.after_render = route_options.after_render;
        }
        routes.push(r);
    }

    var leading_hash_matcher = /^#/;

    /*  go: navigate to the current page
    */
    this.go = function() {
        var page = window.location.hash.replace(leading_hash_matcher, '');

        for (var i = 0; i < routes.length; i++) {
            var m = page.match(routes[i].matcher);
            if (m){
                var args = m.slice(1,m.length);
                var content = routes[i].generator.apply(null, args);
                navigate(page, content, routes[i]);
                return;
            }
        }
        // if we get here, it's effectively a 404, which we'll just ignore
        // TOOD: support options.four_oh_four
    }

    /*  back: navigate to the previously visited page
    */
    this.back = function() {
        var l = history.length;

        if (l > 1) {
            /* pop current page */
            //history.pop()
            /* go previous page */
            //navigate(history[l-2].p, history[l-2].c, history[l-2].r);
            window.location.hash = history[l-2].p;
        }
        // else, silently do nothing
        // TODO: is this appropriate behavior?
    }

    var call_after_render = function(route) {
        if (options.after_render) {
            options.after_render();
        }
        if (route.after_render) {
            route.after_render();
        }
    }

    /** Private Methods **/

    var navigate = function(page, content, route) {
        // TODO: restructure code to move history modification, calls
        // to slide, and calling after_render callback in separate function
        var l = history.length;

        if (l === 0) {  /* No history */
            history.push({p: page, r: route});
            slide(content);
        } else if (history[l-1].p === page) {  /* Same page */
            if (options.allow_reloads || route.allow_reloads) {
                /* Don't push to history, but reload content */
                slide(content);
            } else {
                // trying visit same page, but we're ignoring reloads
                return;
            }
        } else if (l > 1 && page === history[l-2].p) { /* Previous page */
            /* Slide from the left and pop current page from history */
            history.pop();
            slide(content, 'left');
        } else if (typeof route.top_level_tab_index != 'undefined') {
            /* It's one of the top level pages; clear history and add current
               page to it, and then transition according to previously visited
               top-level page and use options */
            var t_idx = history[0].r.top_level_tab_index;
            if (typeof t_idx === 'undefined' || t_idx === route.top_level_tab_index ||
                    options.always_transition_top_level_pages_from_center) {
                slide(content);
            } else {
                var direction = (route.top_level_tab_index < t_idx) ? ('left') : ('right');
                slide(content, direction);
            }
            history = [{p: page, r: route}];
        } else {
            /* New page to push on history stack */
            history.push({p: page, r: route});
            slide(content, 'right');
        }

        call_after_render(route);
    }

    var first_page = true;

    var slide = function(content, from) {
        if (first_page) {
            /* Insert content with no transition effect */
            $('#' + container_id).html(content);
            first_page = false;
        } else {
            var old_container = $('#' + container_id);
            old_container.attr('id', container_id + '___rlj32489fd'); // TODO: use guid to ensure uniqueness

            add_new_content(content, from, old_container);
            var new_container = $('#' + container_id);

            // Force reflow. More information here:
            // http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
            old_container.offsetWidth;
            new_container.offsetWidth;

            transition(from, old_container, new_container);
        }

    }

    var add_new_content = function(content, from, old_container) {
        var cls = "hashnav-page";

        /* add class to position left of, right of, or below viewable region */
        if (from === 'left') {
            cls += ' hashnav-left';
        } else if (from === 'right') {
            cls += ' hashnav-right';
        } else {
            cls += ' hashnav-below';
        }

        /* add container's original classes */
        cls += ' ' + old_container.attr('class');

        old_container.after('
' + content + '
');
    }

    var transition = function(from, old_container, new_container) {
        var container_class = old_container.attr('class');

        old_container.one('webkitTransitionEnd', function(e) {
            $('#' + old_container.attr('id')).remove();
            new_container.attr('class', container_class);
        });
        // new_container.one('webkitTransitionEnd', function(e) {
        //     new_container.attr('class', container_class)
        // })

        old_container.attr('class', [container_class, old_container_class(from)].join(' '));
        new_container.attr('class', [container_class, new_container_class()].join(' '));
    }

    var old_container_class = function(from) {
        var cls = 'hashnav-page hashnav-transition';
        if (from === 'left') {
            cls += ' hashnav-right';
        } else if (from === 'right') {
            cls += ' hashnav-left';
        } else {
            cls += ' hashnav-above';
        }

        return cls;
    }

    var new_container_class = function() {
        return 'hashnav-page hashnav-transition hashnav-center';
    }

    $(window).on('hashchange', this.go);
}
<commit_msg>Use 'unique' guid for old container's id<commit_after>/*  HashNav is ...
    It was inspired by https://github.com/ccoenraets/PageSlider

    @note: this library depends on jquery core.

    General Usage:
        var hashnav = new HashNav(container_id, options);

    Example use:
        var hashnav = new HashNav('container');
        hashnav.add_route("/foo/", {top_level_tab_index: 0}, function(a){ return '
Foo
'; };
        hashnav.add_route("/foo/(.*)/bar", function(a){ return '
Foo: ' + a + '
'; })
        hashnav.add_route("/foo/(.*)/bar", function(a){ return '
Bar: ' + a + '
'; })
        hashnav.add_route("/foo/(.*)/baz", function(a){ return '
Baz: ' + a + '
'; })

    Options:
     - allow_reloads -- regenerate same page twice in a row; this can also be
        specified per route; possible use case is if route involves querying
        of possibly chnging data from server
     - always_transition_top_level_pages_from_center -- Don't use left/right
        transition effect when going from one top level tab
     - after_render -- callback to be executed after rendering any route
        (called before any route-specific after-render callback)
*/

function HashNav(container_id, options) {
    options = options || {};

    var history = [];
    var routes = [];

    var path_param_matcher = /:[^/]+/g;

    /** Public Interface **/

    /*  add_route: associates routes matching a pattern with a content generator.
        @todo: switch 'generator' and 'options' args and support missing options

        Options:
         - allow_reloads -- same meaning as global option of same name, except
            specific to this route.
         - top_level_tab_index -- use for animating left/right transition between
            top level tabs
         - after_render -- callback to be executed after rendering this route
            (called after any global after-render callback)
    */
    this.add_route = function(pattern, route_options, generator) {
        if (typeof route_options == 'function') {
            generator = route_options;
            route_options = {};
        } else {
            route_options = route_options || {};
        }

        //pattern = pattern.replace(/\/*$/, ''); /* so that we match with or with trailing slash */

        pattern = pattern.replace(path_param_matcher, '([^/]+)');

        var r = {
            matcher: RegExp("^" + pattern + "$"),
            generator: generator
        };
        if (typeof route_options.top_level_tab_index != 'undefined') {
            r.top_level_tab_index = route_options.top_level_tab_index;
        }
        if (typeof route_options.after_render != 'undefined') {
            r.after_render = route_options.after_render;
        }
        routes.push(r);
    }

    var leading_hash_matcher = /^#/;

    /*  go: navigate to the current page
    */
    this.go = function() {
        var page = window.location.hash.replace(leading_hash_matcher, '');

        for (var i = 0; i < routes.length; i++) {
            var m = page.match(routes[i].matcher);
            if (m){
                var args = m.slice(1,m.length);
                var content = routes[i].generator.apply(null, args);
                navigate(page, content, routes[i]);
                return;
            }
        }
        // if we get here, it's effectively a 404, which we'll just ignore
        // TOOD: support options.four_oh_four
    }

    /*  back: navigate to the previously visited page
    */
    this.back = function() {
        var l = history.length;

        if (l > 1) {
            /* pop current page */
            //history.pop()
            /* go previous page */
            //navigate(history[l-2].p, history[l-2].c, history[l-2].r);
            window.location.hash = history[l-2].p;
        }
        // else, silently do nothing
        // TODO: is this appropriate behavior?
    }

    var call_after_render = function(route) {
        if (options.after_render) {
            options.after_render();
        }
        if (route.after_render) {
            route.after_render();
        }
    }

    /** Private Methods **/

    var navigate = function(page, content, route) {
        // TODO: restructure code to move history modification, calls
        // to slide, and calling after_render callback in separate function
        var l = history.length;

        if (l === 0) {  /* No history */
            history.push({p: page, r: route});
            slide(content);
        } else if (history[l-1].p === page) {  /* Same page */
            if (options.allow_reloads || route.allow_reloads) {
                /* Don't push to history, but reload content */
                slide(content);
            } else {
                // trying visit same page, but we're ignoring reloads
                return;
            }
        } else if (l > 1 && page === history[l-2].p) { /* Previous page */
            /* Slide from the left and pop current page from history */
            history.pop();
            slide(content, 'left');
        } else if (typeof route.top_level_tab_index != 'undefined') {
            /* It's one of the top level pages; clear history and add current
               page to it, and then transition according to previously visited
               top-level page and use options */
            var t_idx = history[0].r.top_level_tab_index;
            if (typeof t_idx === 'undefined' || t_idx === route.top_level_tab_index ||
                    options.always_transition_top_level_pages_from_center) {
                slide(content);
            } else {
                var direction = (route.top_level_tab_index < t_idx) ? ('left') : ('right');
                slide(content, direction);
            }
            history = [{p: page, r: route}];
        } else {
            /* New page to push on history stack */
            history.push({p: page, r: route});
            slide(content, 'right');
        }

        call_after_render(route);
    }

    var first_page = true;

    var slide = function(content, from) {
        if (first_page) {
            /* Insert content with no transition effect */
            $('#' + container_id).html(content);
            first_page = false;
        } else {
            var old_container = $('#' + container_id);
            old_container.attr('id', container_id + guid());

            add_new_content(content, from, old_container);
            var new_container = $('#' + container_id);

            // Force reflow. More information here:
            // http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/
            old_container.offsetWidth;
            new_container.offsetWidth;

            transition(from, old_container, new_container);
        }

    }

    var guid = function() {
        return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    }

    var add_new_content = function(content, from, old_container) {
        var cls = "hashnav-page";

        /* add class to position left of, right of, or below viewable region */
        if (from === 'left') {
            cls += ' hashnav-left';
        } else if (from === 'right') {
            cls += ' hashnav-right';
        } else {
            cls += ' hashnav-below';
        }

        /* add container's original classes */
        cls += ' ' + old_container.attr('class');

        old_container.after('
' + content + '
');
    }

    var transition = function(from, old_container, new_container) {
        var container_class = old_container.attr('class');

        old_container.one('webkitTransitionEnd', function(e) {
            $('#' + old_container.attr('id')).remove();
            new_container.attr('class', container_class);
        });
        // new_container.one('webkitTransitionEnd', function(e) {
        //     new_container.attr('class', container_class)
        // })

        old_container.attr('class', [container_class, old_container_class(from)].join(' '));
        new_container.attr('class', [container_class, new_container_class()].join(' '));
    }

    var old_container_class = function(from) {
        var cls = 'hashnav-page hashnav-transition';
        if (from === 'left') {
            cls += ' hashnav-right';
        } else if (from === 'right') {
            cls += ' hashnav-left';
        } else {
            cls += ' hashnav-above';
        }

        return cls;
    }

    var new_container_class = function() {
        return 'hashnav-page hashnav-transition hashnav-center';
    }

    $(window).on('hashchange', this.go);
}
<|endoftext|>


<commit_before><commit_msg>Add stats for latest singleword export<commit_after><|endoftext|>


<commit_before>Application.Controllers.controller('toolbarMaterials',
    ["$scope", "mcapi", function ($scope, mcapi) {
        $scope.material = {
            "additional": []
        };

        mcapi('/templates')
            .argWithValue('filter_by', '"template_type":"material"')
            .success(function (data) {
                console.dir(data);
                $scope.material_template = data[0];
                $scope.default_properties = $scope.material_template.model.default;
                $scope.additional_properties = $scope.material_template.model.additional;

            })
            .error(function (e) {

            }).jsonp();

        mcapi('/materials')
            .success(function (data) {
                $scope.materials_list = data;

            })
            .error(function (data) {
            }).jsonp();

        $scope.clear_material = function () {

            $scope.material = {
                "additional": []
            };
        }

            $scope.save = function () {
                $scope.default_properties.forEach(function (item) {
                    $scope.material[item.name] = item.value;
                });
                mcapi('/materials/new')
                    .arg('order_by=birthtime')
                    .success(function (data) {
                        mcapi('/materials/%', data.id)
                            .success(function (material_obj) {
                                $scope.mat = material_obj;
                                $scope.materials_list.unshift(material_obj);
                            })
                            .error(function (e) {

                            }).jsonp();
                        $scope.material = {
                            "additional": []
                        };
                    })
                    .error(function (e) {

                    }).post($scope.material);
            };

            $scope.add_property_to_machine = function () {
                if ($scope.p_name || $scope.p_name === ' ') {
                    $scope.material.additional.push(JSON.parse($scope.p_name));
                    $scope.p_name = '';
                }
                if ($scope.additional_prop || $scope.additional_prop === ' ') {
                    $scope.material.additional.push({'name': $scope.additional_prop, 'value': '', 'value_choice': [],
                        'unit_choice': [], 'unit': '', 'required': 'False', "type": ""});
                    $scope.additional_prop = '';
                }

            };
        }
        ])
        ;<commit_msg>Remove console.dir() call.<commit_after>Application.Controllers.controller('toolbarMaterials',
    ["$scope", "mcapi", function ($scope, mcapi) {
        $scope.material = {
            "additional": []
        };

        mcapi('/templates')
            .argWithValue('filter_by', '"template_type":"material"')
            .success(function (data) {
                $scope.material_template = data[0];
                $scope.default_properties = $scope.material_template.model.default;
                $scope.additional_properties = $scope.material_template.model.additional;

            })
            .error(function (e) {

            }).jsonp();

        mcapi('/materials')
            .success(function (data) {
                $scope.materials_list = data;

            })
            .error(function (data) {
            }).jsonp();

        $scope.clear_material = function () {

            $scope.material = {
                "additional": []
            };
        }

            $scope.save = function () {
                $scope.default_properties.forEach(function (item) {
                    $scope.material[item.name] = item.value;
                });
                mcapi('/materials/new')
                    .arg('order_by=birthtime')
                    .success(function (data) {
                        mcapi('/materials/%', data.id)
                            .success(function (material_obj) {
                                $scope.mat = material_obj;
                                $scope.materials_list.unshift(material_obj);
                            })
                            .error(function (e) {

                            }).jsonp();
                        $scope.material = {
                            "additional": []
                        };
                    })
                    .error(function (e) {

                    }).post($scope.material);
            };

            $scope.add_property_to_machine = function () {
                if ($scope.p_name || $scope.p_name === ' ') {
                    $scope.material.additional.push(JSON.parse($scope.p_name));
                    $scope.p_name = '';
                }
                if ($scope.additional_prop || $scope.additional_prop === ' ') {
                    $scope.material.additional.push({'name': $scope.additional_prop, 'value': '', 'value_choice': [],
                        'unit_choice': [], 'unit': '', 'required': 'False', "type": ""});
                    $scope.additional_prop = '';
                }

            };
        }
        ])
        ;<|endoftext|>


<commit_before>// Remplacez la valeur UA-XXXXXX-Y par l'identifiant analytics de votre site.
gaProperty = 'UA-XXXXXX-Y'

// Désactive le tracking si le cookie d’Opt-out existe déjà.

var disableStr = 'ga-disable-' + gaProperty;
var firstCall = false;
var scrollMax = 0;

//Cette fonction retourne la date d’expiration du cookie de consentement

function getCookieExpireDate() {
 var cookieTimeout = 33696000000;// Le nombre de millisecondes que font 13 mois
 var date = new Date();
 date.setTime(date.getTime()+cookieTimeout);
 var expires = "; expires="+date.toGMTString();
 return expires;
}

//Cette fonction vérifie si on  a déjà obtenu le consentement de la personne qui visite le site
function checkFirstVisit() {
   var consentCookie =  getCookie('hasConsent');
   if ( !consentCookie ) return true;
}

//Affiche une  banniére d'information en haut de la page
 function showBanner(){
    var bodytag = document.getElementsByTagName('body')[0];
    var div = document.createElement('div');
    div.setAttribute('id','cookie-banner');
    div.setAttribute('width','70%');
    // Le code HTML de la demande de consentement
    // Vous pouvez modifier le contenu ainsi que le style
        div.innerHTML =  '
Ce site utilise Google Analytics.\
    En continuant à naviguer, vous nous autorisez à déposer un cookie à des fins de \
    mesure d\'audience.
\
     En savoir plus ou s\'opposer .
';
    bodytag.insertBefore(div,bodytag.firstChild); // Ajoute la banniére juste au début de la page
    document.getElementsByTagName('body')[0].className+=' cookiebanner';
    createInformAndAskDiv();
 }

 function updateBannerOnScrollBanner(){
    var div = document.getElementById('cookie-banner');
      if ( div!= null ) div.innerHTML =  '
Ce site utilise Google Analytics.\
    Si vous continuez à scroller, nous déposerons un cookie à des fins de \
    mesure d\'audience.
\
     En savoir plus ou s\'opposer .
';
 }

 function updateBannerConsented(){
    var div = document.getElementById('cookie-banner');
     if ( div!= null ) div.innerHTML =  '
Ce site utilise Google Analytics.\
    Vous avez consenti au dépôt d\'un cookie à des fins de \
    mesure d\'audience.
\
     Pour vous y opposer.
';
 }

// Fonction utile pour récupérer un cookie a partire de son nom
function getCookie(NameOfCookie)  {
    if (document.cookie.length > 0) {
        begin = document.cookie.indexOf(NameOfCookie+"=");
        if (begin != -1)  {
            begin += NameOfCookie.length+1;
            end = document.cookie.indexOf(";", begin);
            if (end == -1) end = document.cookie.length;
            return unescape(document.cookie.substring(begin, end));
        }
     }
    return null;
}

//Récupère la version d'Internet Explorer, si c'est un autre navigateur la fonction renvoie -1
function getInternetExplorerVersion() {
  var rv = -1;
  if (navigator.appName == 'Microsoft Internet Explorer')  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }  else if (navigator.appName == 'Netscape')  {
    var ua = navigator.userAgent;
    var re  = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}

//Effectue une demande de confirmation de DNT pour les utilisateurs d'IE
function askDNTConfirmation() {
	var r = confirm("La signal DoNotTrack de votre navigateur est activé, confirmez vous activer la fonction DoNotTrack?")
	return r;
}

//Vérifie la valeur de navigator.DoNotTrack pour savoir si le signal est activé et est à 1
function notToTrack() {
if ( (navigator.doNotTrack && (navigator.doNotTrack=='yes' || navigator.doNotTrack=='1')) || ( navigator.msDoNotTrack && navigator.msDoNotTrack == '1') ) {
 	var isIE = (getInternetExplorerVersion()!=-1)
 	if (!isIE){
		 return true;
 	}else {
		return askDNTConfirmation();
	}
	return false;
}
}

//Si le signal est à 0 on considére que le consentement a déjà été obtenu
function isToTrack() {
	if ( navigator.doNotTrack && (navigator.doNotTrack=='no' || navigator.doNotTrack==0 )) {
 		return true;
	}
}

// Fonction d'effacement des cookies
function delCookie(name )   {
    var path = ";path=" + "/";
	var hostname = document.location.hostname;
	if (hostname.indexOf("www.") === 0)
		hostname = hostname.substring(4);
    var domain = ";domain=" + "."+hostname;
    var expiration = "Thu, 01-Jan-1970 00:00:01 GMT";
    document.cookie = name + "=" + path + domain + ";expires=" + expiration;
}

// Efface tous les types de cookies utilisés par Google Analytics
function deleteAnalyticsCookies() {
    var cookieNames = ["__utma","__utmb","__utmc","__utmz","_ga"]
    for (var i=0; i<cookieNames.length; i++)
        delCookie(cookieNames[i])
}

//La fonction qui informe et demande le consentement. Il s'agit d'un div qui apparait au centre de la page
function createInformAndAskDiv() {
    var bodytag = document.getElementsByTagName('body')[0];
    var div = document.createElement('div');
    div.setAttribute('id','inform-and-ask');
    div.style.width= window.innerWidth+"px" ;
    div.style.height= window.innerHeight+"px";
    //div.style.opacity = 0.75;
    div.style.display= "none";
    div.style.position= "fixed";
    //div.style.backgroundColor = "white";
    // Le code HTML de la demande de consentement
    // Vous pouvez modifier le contenu ainsi que le style
    div.innerHTML =  '
\

Les cookies Google Analytics

Ce site utilise  des cookies de Google Analytics,\
	ces cookies nous aident à identifier le contenu qui vous interesse le plus ainsi qu\'à repérer certains \
	disfonctionnements. Vos données de navigations sur ce site sont envoyées à Google Inc

<button \
	name="S\'opposer" onclick="gaOptout();hideInform();" id="optout-button" >S\'opposer</button>	<button name="cancel" onclick="hideInform()" >Accepter</button>

'
    bodytag.insertBefore(div,bodytag.firstChild); // Ajoute la banniére juste au début de la page
}

function showInform() {
	var div = document.getElementById("inform-and-ask");
	div.style.display = "";
}

function hideInform() {
	var div = document.getElementById("inform-and-ask");
	div.style.display = "none";
}

// La fonction d'opt-out
function gaOptout() {
    document.cookie = disableStr + '=true;'+ getCookieExpireDate() +' ; path=/';
    document.cookie = 'hasConsent=false;'+ getCookieExpireDate() +' ; path=/';
    var div = document.getElementById('cookie-banner');
    // Ci dessous le code de la bannière affichée une fois que l'utilisateur s'est opposé au dépot
    // Vous pouvez modifier le contenu et le style
    if ( div!= null ) div.innerHTML = '
 Vous vous êtes opposé \
    au dépôt de cookies de mesures d\'audience dans votre navigateur
'
    window[disableStr] = true;
    deleteAnalyticsCookies();
}

function isClickOnOptOut( evt) { // Si le noeud parent ou le noeud parent du parent est la banniére, on ignore le clic
	return(evt.target.parentNode.id == 'cookie-banner' || evt.target.parentNode.parentNode.id =='cookie-banner' || evt.target.id == 'optout-button')
}

function consent(evt) {
	if (!isClickOnOptOut(evt) ) { // On vérifie qu'il ne s'agit pas d'un clic sur la banniére
		if ( !clickprocessed) {
			evt.preventDefault();
			document.cookie = 'hasConsent=true; '+ getCookieExpireDate() +' ; path=/';
			callGoogleAnalytics();
			clickprocessed = true;
			window.setTimeout(function() {evt.target.click();}, 1000)
		}
	}
}

// Cette fonction en test permet de faire une call GA  afin de pouvoir compter le nombre de visite sans faire de suivi des utilisateurs (fonction en cours de test)
// Cela crée un evenement page qui est consultable depuis le panneau evenement de GA
// Potentiellement cette méthode pourrait être utilisé pour comptabiliser les click sur l'opt-out
function callGABeforeConsent() {
	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','//www.google-analytics.com/analytics.js','__gaTracker');
	// Ici on desactive les cookie
	__gaTracker('create', gaProperty, { 'storage': 'none', 'clientId': '0'});
	__gaTracker('send', 'event', 'page', 'load', {'nonInteraction': 1});
}

//Si vous souhaitez considérer le scroll comme une action positive (ce qui ne correspond pas à la cinématique en deux étapes  recommandée) utilisez ce code
function consentByScroll() {
	scrollMax = Math.max(scrollMax,window.pageYOffset);
	if (scrollMax < 600) {
		updateBannerOnScrollBanner();
	}
	if (scrollMax  > 600) {
			document.cookie = 'hasConsent=true; '+ getCookieExpireDate() +' ; path=/';
			callGoogleAnalytics();
			updateBannerConsented();
	}
	if (window.pageYOffset == 0) {
		var div = document.getElementById('cookie-banner-message');
    		// Ci dessous le code de la bannière affichée une fois que l'utilisateur s'est opposé au dépôt
   		 if ( div!= null ) div.style.position = 'relative';
	}
}

// Tag Google Analytics, cette version est avec le tag Universal Analytics
function callGoogleAnalytics() {
	if (firstCall) return;
	else firstCall = true;
	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
	ga('create', gaProperty, 'auto');  // Replace with your property ID.
	ga('send', 'pageview');
}

//Ce bout de code vérifie que le consentement n'a pas déjà été obtenu avant d'afficher
// la banniére
var consentCookie =  getCookie('hasConsent');
clickprocessed = false;
if (!consentCookie) {//L'utilisateur n'a pas encore de cookie, on affiche la banniére et si il clique sur un autre élément que la banniére, on enregistre le consentement
	if ( notToTrack() ) { //L'utilisateur a activé DoNotTrack. Do not ask for consent and just opt him out
		gaOptout()
		alert("You've enabled DNT, we're respecting your choice")
	} else {
		if (isToTrack() ) { //DNT is set to 0, no need to ask for consent just set cookies
			consent();
		} else {
			window.onload = showBanner;
			//window.onscroll = consentByScroll; // Méthode de consentement non recommandée
			document.onclick = consent;
			callGABeforeConsent()
		}
	}
} else {
	if (document.cookie.indexOf('hasConsent=false') > -1)
		window[disableStr] = true;
	else
		window[disableStr] = false;
		callGoogleAnalytics();
}

<commit_msg>Typos<commit_after>// Remplacez la valeur UA-XXXXXX-Y par l'identifiant analytics de votre site.
gaProperty = 'UA-XXXXXX-Y'

// Désactive le tracking si le cookie d’Opt-out existe déjà.

var disableStr = 'ga-disable-' + gaProperty;
var firstCall = false;
var scrollMax = 0;

//Cette fonction retourne la date d’expiration du cookie de consentement

function getCookieExpireDate() {
 var cookieTimeout = 33696000000;// Le nombre de millisecondes que font 13 mois
 var date = new Date();
 date.setTime(date.getTime()+cookieTimeout);
 var expires = "; expires="+date.toGMTString();
 return expires;
}

//Cette fonction vérifie si on  a déjà obtenu le consentement de la personne qui visite le site
function checkFirstVisit() {
   var consentCookie =  getCookie('hasConsent');
   if ( !consentCookie ) return true;
}

//Affiche une  banniére d'information en haut de la page
 function showBanner(){
    var bodytag = document.getElementsByTagName('body')[0];
    var div = document.createElement('div');
    div.setAttribute('id','cookie-banner');
    div.setAttribute('width','70%');
    // Le code HTML de la demande de consentement
    // Vous pouvez modifier le contenu ainsi que le style
        div.innerHTML =  '
Ce site utilise Google Analytics.\
    En continuant à naviguer, vous nous autorisez à déposer un cookie à des fins de \
    mesure d\'audience.
\
     En savoir plus ou s\'opposer .
';
    bodytag.insertBefore(div,bodytag.firstChild); // Ajoute la banniére juste au début de la page
    document.getElementsByTagName('body')[0].className+=' cookiebanner';
    createInformAndAskDiv();
 }

 function updateBannerOnScrollBanner(){
    var div = document.getElementById('cookie-banner');
      if ( div!= null ) div.innerHTML =  '
Ce site utilise Google Analytics.\
    Si vous continuez à scroller, nous déposerons un cookie à des fins de \
    mesure d\'audience.
\
     En savoir plus ou s\'opposer .
';
 }

 function updateBannerConsented(){
    var div = document.getElementById('cookie-banner');
     if ( div!= null ) div.innerHTML =  '
Ce site utilise Google Analytics.\
    Vous avez consenti au dépôt d\'un cookie à des fins de \
    mesure d\'audience.
\
     Pour vous y opposer.
';
 }

// Fonction utile pour récupérer un cookie a partire de son nom
function getCookie(NameOfCookie)  {
    if (document.cookie.length > 0) {
        begin = document.cookie.indexOf(NameOfCookie+"=");
        if (begin != -1)  {
            begin += NameOfCookie.length+1;
            end = document.cookie.indexOf(";", begin);
            if (end == -1) end = document.cookie.length;
            return unescape(document.cookie.substring(begin, end));
        }
     }
    return null;
}

//Récupère la version d'Internet Explorer, si c'est un autre navigateur la fonction renvoie -1
function getInternetExplorerVersion() {
  var rv = -1;
  if (navigator.appName == 'Microsoft Internet Explorer')  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }  else if (navigator.appName == 'Netscape')  {
    var ua = navigator.userAgent;
    var re  = new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
}

//Effectue une demande de confirmation de DNT pour les utilisateurs d'IE
function askDNTConfirmation() {
	var r = confirm("La signal DoNotTrack de votre navigateur est activé, confirmez vous activer la fonction DoNotTrack?")
	return r;
}

//Vérifie la valeur de navigator.DoNotTrack pour savoir si le signal est activé et est à 1
function notToTrack() {
if ( (navigator.doNotTrack && (navigator.doNotTrack=='yes' || navigator.doNotTrack=='1')) || ( navigator.msDoNotTrack && navigator.msDoNotTrack == '1') ) {
 	var isIE = (getInternetExplorerVersion()!=-1)
 	if (!isIE){
		 return true;
 	}else {
		return askDNTConfirmation();
	}
	return false;
}
}

//Si le signal est à 0 on considére que le consentement a déjà été obtenu
function isToTrack() {
	if ( navigator.doNotTrack && (navigator.doNotTrack=='no' || navigator.doNotTrack==0 )) {
 		return true;
	}
}

// Fonction d'effacement des cookies
function delCookie(name )   {
    var path = ";path=" + "/";
	var hostname = document.location.hostname;
	if (hostname.indexOf("www.") === 0)
		hostname = hostname.substring(4);
    var domain = ";domain=" + "."+hostname;
    var expiration = "Thu, 01-Jan-1970 00:00:01 GMT";
    document.cookie = name + "=" + path + domain + ";expires=" + expiration;
}

// Efface tous les types de cookies utilisés par Google Analytics
function deleteAnalyticsCookies() {
    var cookieNames = ["__utma","__utmb","__utmc","__utmz","_ga"]
    for (var i=0; i<cookieNames.length; i++)
        delCookie(cookieNames[i])
}

//La fonction qui informe et demande le consentement. Il s'agit d'un div qui apparait au centre de la page
function createInformAndAskDiv() {
    var bodytag = document.getElementsByTagName('body')[0];
    var div = document.createElement('div');
    div.setAttribute('id','inform-and-ask');
    div.style.width= window.innerWidth+"px" ;
    div.style.height= window.innerHeight+"px";
    //div.style.opacity = 0.75;
    div.style.display= "none";
    div.style.position= "fixed";
    //div.style.backgroundColor = "white";
    // Le code HTML de la demande de consentement
    // Vous pouvez modifier le contenu ainsi que le style
    div.innerHTML =  '
\

Les cookies Google Analytics

Ce site utilise  des cookies de Google Analytics,\
	ces cookies nous aident à identifier le contenu qui vous interesse le plus ainsi qu\'à repérer certains \
	dysfonctionnements. Vos données de navigations sur ce site sont envoyées à Google Inc

<button \
	name="S\'opposer" onclick="gaOptout();hideInform();" id="optout-button" >S\'opposer</button>	<button name="cancel" onclick="hideInform()" >Accepter</button>

'
    bodytag.insertBefore(div,bodytag.firstChild); // Ajoute la banniére juste au début de la page
}

function showInform() {
	var div = document.getElementById("inform-and-ask");
	div.style.display = "";
}

function hideInform() {
	var div = document.getElementById("inform-and-ask");
	div.style.display = "none";
}

// La fonction d'opt-out
function gaOptout() {
    document.cookie = disableStr + '=true;'+ getCookieExpireDate() +' ; path=/';
    document.cookie = 'hasConsent=false;'+ getCookieExpireDate() +' ; path=/';
    var div = document.getElementById('cookie-banner');
    // Ci dessous le code de la bannière affichée une fois que l'utilisateur s'est opposé au dépot
    // Vous pouvez modifier le contenu et le style
    if ( div!= null ) div.innerHTML = '
 Vous vous êtes opposé \
    au dépôt de cookies de mesures d\'audience dans votre navigateur
'
    window[disableStr] = true;
    deleteAnalyticsCookies();
}

function isClickOnOptOut( evt) { // Si le noeud parent ou le noeud parent du parent est la banniére, on ignore le clic
	return(evt.target.parentNode.id == 'cookie-banner' || evt.target.parentNode.parentNode.id =='cookie-banner' || evt.target.id == 'optout-button')
}

function consent(evt) {
	if (!isClickOnOptOut(evt) ) { // On vérifie qu'il ne s'agit pas d'un clic sur la banniére
		if ( !clickprocessed) {
			evt.preventDefault();
			document.cookie = 'hasConsent=true; '+ getCookieExpireDate() +' ; path=/';
			callGoogleAnalytics();
			clickprocessed = true;
			window.setTimeout(function() {evt.target.click();}, 1000)
		}
	}
}

// Cette fonction en test permet de faire une call GA  afin de pouvoir compter le nombre de visite sans faire de suivi des utilisateurs (fonction en cours de test)
// Cela crée un evenement page qui est consultable depuis le panneau evenement de GA
// Potentiellement cette méthode pourrait être utilisé pour comptabiliser les click sur l'opt-out
function callGABeforeConsent() {
	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','//www.google-analytics.com/analytics.js','__gaTracker');
	// Ici on desactive les cookie
	__gaTracker('create', gaProperty, { 'storage': 'none', 'clientId': '0'});
	__gaTracker('send', 'event', 'page', 'load', {'nonInteraction': 1});
}

//Si vous souhaitez considérer le scroll comme une action positive (ce qui ne correspond pas à la cinématique en deux étapes  recommandée) utilisez ce code
function consentByScroll() {
	scrollMax = Math.max(scrollMax,window.pageYOffset);
	if (scrollMax < 600) {
		updateBannerOnScrollBanner();
	}
	if (scrollMax  > 600) {
			document.cookie = 'hasConsent=true; '+ getCookieExpireDate() +' ; path=/';
			callGoogleAnalytics();
			updateBannerConsented();
	}
	if (window.pageYOffset == 0) {
		var div = document.getElementById('cookie-banner-message');
    		// Ci dessous le code de la bannière affichée une fois que l'utilisateur s'est opposé au dépôt
   		 if ( div!= null ) div.style.position = 'relative';
	}
}

// Tag Google Analytics, cette version est avec le tag Universal Analytics
function callGoogleAnalytics() {
	if (firstCall) return;
	else firstCall = true;
	(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
	ga('create', gaProperty, 'auto');  // Replace with your property ID.
	ga('send', 'pageview');
}

//Ce bout de code vérifie que le consentement n'a pas déjà été obtenu avant d'afficher
// la bannière
var consentCookie =  getCookie('hasConsent');
clickprocessed = false;
if (!consentCookie) {//L'utilisateur n'a pas encore de cookie, on affiche la banniére et si il clique sur un autre élément que la banniére, on enregistre le consentement
	if ( notToTrack() ) { //L'utilisateur a activé DoNotTrack. Do not ask for consent and just opt him out
		gaOptout()
		alert("You've enabled DNT, we're respecting your choice")
	} else {
		if (isToTrack() ) { //DNT is set to 0, no need to ask for consent just set cookies
			consent();
		} else {
			window.onload = showBanner;
			//window.onscroll = consentByScroll; // Méthode de consentement non recommandée
			document.onclick = consent;
			callGABeforeConsent()
		}
	}
} else {
	if (document.cookie.indexOf('hasConsent=false') > -1)
		window[disableStr] = true;
	else
		window[disableStr] = false;
		callGoogleAnalytics();
}

<|endoftext|>