<commit_before>( // Module boilerplate to support browser globals, node.js and AMD.
  (typeof module !== "undefined" && function (m) { module.exports = m(require('./runtime')); }) ||
  (typeof define === "function" && function (m) { define(["./runtime"], m); }) ||
  (function (m) { window.brozula = window.brozula || {}; window.brozula.globals = m(window.brozula.runtime); })
)(function (runtime) {

var falsy = runtime.falsy;
var slice = Array.prototype.slice;
var next = runtime.next;
var inext = runtime.inext;

var file = {
  close: function () { throw new Error("TODO: Implement io.file.close"); },
  flush: function () { throw new Error("TODO: Implement io.file.flush"); },
  lines: function () { throw new Error("TODO: Implement io.file.lines"); },
  read: function () { throw new Error("TODO: Implement io.file.read"); },
  seek: function () { throw new Error("TODO: Implement io.file.seek"); },
  setvbuf: function () { throw new Error("TODO: Implement io.file.setvbuf"); },
  write: function () { throw new Error("TODO: Implement io.file.write"); }
};

var _G = {
  _VERSION: "Lua 5.1",
  assert: function assert(expr, message) {
    if (falsy(expr)) throw message;
    return slice.call(arguments);
  },
  bit: {},
  collectgarbage: function collectgarbage() { throw new Error("TODO: Implement collectgarbage"); },
  coroutine: {
    create: function () { throw new Error("TODO: Implement coroutine.create"); },
    resume: function () { throw new Error("TODO: Implement coroutine.resume"); },
    running: function () { throw new Error("TODO: Implement coroutine.running"); },
    status: function () { throw new Error("TODO: Implement coroutine.status"); },
    wrap: function () { throw new Error("TODO: Implement coroutine.wrap"); },
    yield: function () { throw new Error("TODO: Implement coroutine.yield"); }
  },
  debug: {},
  error: function error(message) {
    throw message;
  },
  gcinfo: function gcinfo() { throw new Error("TODO: Implement gcinfo"); },
  getfenv: function getfenv() { throw new Error("TODO: Implement getfenv"); },
  getmetatable: function getmetatable(tab) {
    return [runtime.getmetatable(tab)];
  },
  io: {
    input: function () { throw new Error("TODO: Implement io.input"); },
    tmpfile: function () { throw new Error("TODO: Implement io.tmpfile"); },
    read: function () { throw new Error("TODO: Implement io.read"); },
    output: function () { throw new Error("TODO: Implement io.output"); },
    open: function () { throw new Error("TODO: Implement io.open"); },
    close: function () { throw new Error("TODO: Implement io.close"); },
    write: function () { throw new Error("TODO: Implement io.write"); },
    popen: function () { throw new Error("TODO: Implement io.popen"); },
    flush: function () { throw new Error("TODO: Implement io.flush"); },
    type: function () { throw new Error("TODO: Implement io.type"); },
    lines: function () { throw new Error("TODO: Implement io.lines"); },
    stdin: file,
    stdout: file,
    stderr: file
  },
  ipairs: function ipairs(tab) {
    return [inext, tab, 0];
  },
  jit: {},
  math: {
    abs:   function (x) { return [Math.abs(x)]; },
    acos:  function (x) { return [Math.acos(x)]; },
    asin:  function (x) { return [Math.asin(x)]; },
    atan:  function (x) { return [Math.atan(x)]; },
    atan2: function (x,y) { return [Math.atan2(x,y)]; },
    ceil:  function (x) { return [Math.ceil(x)]; },
    cos:   function (x) { return [Math.cos(x)]; },
    cosh:  function (x) { return [ ( Math.exp(x)+Math.exp(-x) ) / 2.0 ]; },
    deg:   function (x) { return [x/(Math.PI/180)]; },
    exp:   function (x) { return [Math.exp(x)]; },
    floor: function (x) { return [Math.floor(x)]; },
    fmod:  function (x,y) { return[x % y]; },
    mod:   function (x,y) { return[x % y]; }, //For compatibility
    frexp: function (x) {
      var exp = 0
      while (!(x < 1 & x >= 0.5)){
        exp = exp + 1;
        x /= 2;
      }
      return [x, exp]
    },
    huge:  Infinity,
    ldexp: function (x,exp) { return [x * (2 ^ exp)]; },
    log:   function (x,b) {
      return [ (typeof b === 'undefined' ) ?
        Math.log(x) :
        Math.log(x) / Math.log(b)
      ];
    },
    log10: function (x) { // This is deprecated in Lua 5.2
      return [ Math.log ( x ) / Math.LN10 ];
    },
    max: function (max) {
      for ( var i = 1; i < arguments.length; i++ ) {
        max = Math.max ( max , arguments[i] );
      }
      return [max];
    },
    min: function (min) {
      for ( var i = 1; i < arguments.length; i++ ) {
        min = Math.min ( min , arguments[i] );
      }
      return [min];
    },
    modf: function (x) { return [Math.floor(x), x % 1]; },
    pi: Math.PI,
    pow: function (x) { return [Math.pow(x)]; },
    rad: function (x) { return [x*(Math.PI/180)]; },
    random: function (a,b) {
      var r = Math.random(x);
      switch ( arguments.length ) {
        case 0:
          return [rnd];
        case 1: /* only upper limit */
          if (1>a) { throw new Error("interval is empty"); }
          return [Math.floor(r*a)+1];
        case 2: /* lowe and upper limits */
          if (a>b) { throw new Error("interval is empty"); }
          return [Math.floor(r*(b-a+1))+1];
        default:
          throw new Error("wrong number of arguments");
      }
    },
    randomseed: function () { throw new Error("TODO: Implement math.randomseed"); },
    sin:  function (x) { return [Math.sin(x)]; },
    sinh: function (x) { return [ ( Math.exp(x)-Math.exp(-x) ) / 2.0 ]; },
    sqrt: function (x) { return [Math.sqrt(x)]; },
    tan:  function (x) { return [Math.tan(x)]; },
    tanh: function (x) {
      var ex = Math.exp(x);
      var ey = Math.exp(-x);
      return [ ( ex-ey ) / ( ex + ey ) ];
    }
  },
  module: function module() { throw new Error("TODO: Implement module"); },
  newproxy: function newproxy() { throw new Error("TODO: Implement newproxy"); },
  next: next,
  os: {},
  package: {},
  pairs: function pairs(tab) {
    return [next, tab, null];
  },
  pcall: function pcall() { throw new Error("TODO: Implement pcall"); },
  print: function print() {
    console.log(Array.prototype.map.call(arguments, runtime.tostring).join("\t"));
    return [];
  },
  rawequal: function rawequal() { throw new Error("TODO: Implement rawequal"); },
  rawget: function rawget(tab, key) {
    return [runtime.rawget(tab, key)];
  },
  rawset: function rawset(tab, key, val) {
    runtime.rawset(tab, key, val);
    return [];
  },
  require: function require() { throw new Error("TODO: Implement require"); },
  select: function select(index) {
    if (typeof index === "number") {
      return Array.prototype.slice.call(arguments, index);
    }
    if (index === "#") {
      return arguments.length - 1;
    }
  },
  setfenv: function setfenv() { throw new Error("TODO: Implement setfenv"); },
  setmetatable: function setmetatable(tab, meta) {
    runtime.setmetatable(tab, meta);
    return [tab];
  },
  string: runtime.string,
  table: {
    concat: function (tab, joiner, i , j) {
      if (!(tab && typeof tab === "object")) throw "table expected";
      var slice = tab.array;
      if (arguments.length >= 3 ) {
        slice = slice.slice(i, ((typeof j === "undefined")? slice.length : j) );
      }
      return [slice.join(joiner)];
    },
    insert: function (tab) {
      if (!(tab && typeof tab === "object")) throw "table expected";
      var pos, val;
      if (arguments.length <= 2) {
        pos = tab.array.length+1;
        val = arguments[1];
      } else {
        pos = arguments[1];
        val = arguments[2];
      }
      tab.array.splice( pos, 0, val );
      return [];
    },
    sort: function (tab, cmp) {
      cmp = cmp || lt;
      tab.sort(function (a, b) {
        return cmp(a, b)[0] ? 1 : -1;
      });
      return [];
    },
    remove: function (tab,pos) {
      if (!(tab && typeof tab === "object")) throw "table expected";
      if (arguments.length == 1) {
        pos = 1;
      }
      return tab.array.splice( pos, 1 );
    }
  },
  tonumber: function tonumber(val, base) {
    return [runtime.tonumber(val, base)];
  },
  tostring: function tostring(val) {
    return [runtime.tostring(val)];
  },
  type: function type(val) {
    return [runtime.type(val)];
  },
  unpack: function unpack(tab) {
    return tab;
  },
  xpcall: function xpcall() { throw new Error("TODO: Implement xpcall"); },
  inspect: function (val) {
    console.log(require('util').inspect(val, false, 10, true));
    return [];
  }
};
_G._G = _G;

return _G;

});
<commit_msg>BitOps<commit_after>( // Module boilerplate to support browser globals, node.js and AMD.
  (typeof module !== "undefined" && function (m) { module.exports = m(require('./runtime')); }) ||
  (typeof define === "function" && function (m) { define(["./runtime"], m); }) ||
  (function (m) { window.brozula = window.brozula || {}; window.brozula.globals = m(window.brozula.runtime); })
)(function (runtime) {

var falsy = runtime.falsy;
var slice = Array.prototype.slice;
var next = runtime.next;
var inext = runtime.inext;

var file = {
  close: function () { throw new Error("TODO: Implement io.file.close"); },
  flush: function () { throw new Error("TODO: Implement io.file.flush"); },
  lines: function () { throw new Error("TODO: Implement io.file.lines"); },
  read: function () { throw new Error("TODO: Implement io.file.read"); },
  seek: function () { throw new Error("TODO: Implement io.file.seek"); },
  setvbuf: function () { throw new Error("TODO: Implement io.file.setvbuf"); },
  write: function () { throw new Error("TODO: Implement io.file.write"); }
};

var _G = {
  _VERSION: "Lua 5.1",
  assert: function assert(expr, message) {
    if (falsy(expr)) throw message;
    return slice.call(arguments);
  },
  bit: {
    tobit: function (x) { return [x|0]; };
    tohex: function (x, n) {
      n = n ? n : 8;
      var hex = (x|0).toString(16);
      hex = hex.length >= n ? hex.slice(-n) : new Array(n - hex.length + 1).join('0') + hex;
      return [hex];
    };
    bnot: function (x) { return [~(x|0)]; };
    band: function () {
      var res = 0xffffffff|0;
      for ( var i = 1; i < arguments.length; i++ ) {
        x = arguments[i]|0;
        res = res & x;
      }
      if (arguments.length == 0) { res = 0; }
      return [res];
    };
    bor: function () {
      var res = 0x00000000|0;
      for ( var i = 1; i < arguments.length; i++ ) {
        x = arguments[i]|0;
        res = res | x;
      }
      return [res];
    };
    bxor: function () {
      var res = 0x00000000|0;
      for ( var i = 1; i < arguments.length; i++ ) {
        x = arguments[i]|0;
        res = res ^ x;
      }
      return [res];
    };
    lshift:  function (x,n) { return [x <<  n]; };
    rshift:  function (x,n) { return [x >>> n]; };
    arshift: function (x,n) { return [x >>  n]; };
    rol: function (x, n) {
      var a,b = (x|0) << n, (x|0) >>> (31-n);
      return [(a + b)|0]
    };
    ror: function (x, n) {
      var a,b = (x|0) << (31-n), (x|0) >>> (n);
      return [(a + b)|0]
    };
    bswap: function (n) {
      var hex = (x|0).toString(16);
      hex = new Array(8 - hex.length + 1).join('0') + hex;
      hex = hex.match(/.{1,3}/g);
      return [parseInt(hex.reverse().join(""), 16)];
    };
  },
  collectgarbage: function collectgarbage() { throw new Error("TODO: Implement collectgarbage"); },
  coroutine: {
    create: function () { throw new Error("TODO: Implement coroutine.create"); },
    resume: function () { throw new Error("TODO: Implement coroutine.resume"); },
    running: function () { throw new Error("TODO: Implement coroutine.running"); },
    status: function () { throw new Error("TODO: Implement coroutine.status"); },
    wrap: function () { throw new Error("TODO: Implement coroutine.wrap"); },
    yield: function () { throw new Error("TODO: Implement coroutine.yield"); }
  },
  debug: {},
  error: function error(message) {
    throw message;
  },
  gcinfo: function gcinfo() { throw new Error("TODO: Implement gcinfo"); },
  getfenv: function getfenv() { throw new Error("TODO: Implement getfenv"); },
  getmetatable: function getmetatable(tab) {
    return [runtime.getmetatable(tab)];
  },
  io: {
    input: function () { throw new Error("TODO: Implement io.input"); },
    tmpfile: function () { throw new Error("TODO: Implement io.tmpfile"); },
    read: function () { throw new Error("TODO: Implement io.read"); },
    output: function () { throw new Error("TODO: Implement io.output"); },
    open: function () { throw new Error("TODO: Implement io.open"); },
    close: function () { throw new Error("TODO: Implement io.close"); },
    write: function () { throw new Error("TODO: Implement io.write"); },
    popen: function () { throw new Error("TODO: Implement io.popen"); },
    flush: function () { throw new Error("TODO: Implement io.flush"); },
    type: function () { throw new Error("TODO: Implement io.type"); },
    lines: function () { throw new Error("TODO: Implement io.lines"); },
    stdin: file,
    stdout: file,
    stderr: file
  },
  ipairs: function ipairs(tab) {
    return [inext, tab, 0];
  },
  jit: {},
  math: {
    abs:   function (x) { return [Math.abs(x)]; },
    acos:  function (x) { return [Math.acos(x)]; },
    asin:  function (x) { return [Math.asin(x)]; },
    atan:  function (x) { return [Math.atan(x)]; },
    atan2: function (x,y) { return [Math.atan2(x,y)]; },
    ceil:  function (x) { return [Math.ceil(x)]; },
    cos:   function (x) { return [Math.cos(x)]; },
    cosh:  function (x) { return [ ( Math.exp(x)+Math.exp(-x) ) / 2.0 ]; },
    deg:   function (x) { return [x/(Math.PI/180)]; },
    exp:   function (x) { return [Math.exp(x)]; },
    floor: function (x) { return [Math.floor(x)]; },
    fmod:  function (x,y) { return[x % y]; },
    mod:   function (x,y) { return[x % y]; }, //For compatibility
    frexp: function (x) {
      var exp = 0
      while (!(x < 1 && x >= 0.5)){
        exp = exp + 1;
        x /= 2;
      }
      return [x, exp]
    },
    huge:  Infinity,
    ldexp: function (x,exp) { return [x * (2 ^ exp)]; },
    log:   function (x,b) {
      return [ (typeof b === 'undefined' ) ?
        Math.log(x) :
        Math.log(x) / Math.log(b)
      ];
    },
    log10: function (x) { // This is deprecated in Lua 5.2
      return [ Math.log ( x ) / Math.LN10 ];
    },
    max: function (max) {
      for ( var i = 1; i < arguments.length; i++ ) {
        max = Math.max ( max , arguments[i] );
      }
      return [max];
    },
    min: function (min) {
      for ( var i = 1; i < arguments.length; i++ ) {
        min = Math.min ( min , arguments[i] );
      }
      return [min];
    },
    modf: function (x) { return [Math.floor(x), x % 1]; },
    pi: Math.PI,
    pow: function (x) { return [Math.pow(x)]; },
    rad: function (x) { return [x*(Math.PI/180)]; },
    random: function (a,b) {
      var r = Math.random(x);
      switch ( arguments.length ) {
        case 0:
          return [rnd];
        case 1: /* only upper limit */
          if (1>a) { throw new Error("interval is empty"); }
          return [Math.floor(r*a)+1];
        case 2: /* lowe and upper limits */
          if (a>b) { throw new Error("interval is empty"); }
          return [Math.floor(r*(b-a+1))+1];
        default:
          throw new Error("wrong number of arguments");
      }
    },
    randomseed: function () { throw new Error("TODO: Implement math.randomseed"); },
    sin:  function (x) { return [Math.sin(x)]; },
    sinh: function (x) { return [ ( Math.exp(x)-Math.exp(-x) ) / 2.0 ]; },
    sqrt: function (x) { return [Math.sqrt(x)]; },
    tan:  function (x) { return [Math.tan(x)]; },
    tanh: function (x) {
      var ex = Math.exp(x);
      var ey = Math.exp(-x);
      return [ ( ex-ey ) / ( ex + ey ) ];
    }
  },
  module: function module() { throw new Error("TODO: Implement module"); },
  newproxy: function newproxy() { throw new Error("TODO: Implement newproxy"); },
  next: next,
  os: {},
  package: {},
  pairs: function pairs(tab) {
    return [next, tab, null];
  },
  pcall: function pcall() { throw new Error("TODO: Implement pcall"); },
  print: function print() {
    console.log(Array.prototype.map.call(arguments, runtime.tostring).join("\t"));
    return [];
  },
  rawequal: function rawequal() { throw new Error("TODO: Implement rawequal"); },
  rawget: function rawget(tab, key) {
    return [runtime.rawget(tab, key)];
  },
  rawset: function rawset(tab, key, val) {
    runtime.rawset(tab, key, val);
    return [];
  },
  require: function require() { throw new Error("TODO: Implement require"); },
  select: function select(index) {
    if (typeof index === "number") {
      return Array.prototype.slice.call(arguments, index);
    }
    if (index === "#") {
      return arguments.length - 1;
    }
  },
  setfenv: function setfenv() { throw new Error("TODO: Implement setfenv"); },
  setmetatable: function setmetatable(tab, meta) {
    runtime.setmetatable(tab, meta);
    return [tab];
  },
  string: runtime.string,
  table: {
    concat: function (tab, joiner, i , j) {
      if (!(tab && typeof tab === "object")) throw "table expected";
      var slice = tab.array;
      if (arguments.length >= 3 ) {
        slice = slice.slice(i, ((typeof j === "undefined")? slice.length : j) );
      }
      return [slice.join(joiner)];
    },
    insert: function (tab) {
      if (!(tab && typeof tab === "object")) throw "table expected";
      var pos, val;
      if (arguments.length <= 2) {
        pos = tab.array.length+1;
        val = arguments[1];
      } else {
        pos = arguments[1];
        val = arguments[2];
      }
      tab.array.splice( pos, 0, val );
      return [];
    },
    sort: function (tab, cmp) {
      cmp = cmp || lt;
      tab.sort(function (a, b) {
        return cmp(a, b)[0] ? 1 : -1;
      });
      return [];
    },
    remove: function (tab,pos) {
      if (!(tab && typeof tab === "object")) throw "table expected";
      if (arguments.length == 1) {
        pos = 1;
      }
      return tab.array.splice( pos, 1 );
    }
  },
  tonumber: function tonumber(val, base) {
    return [runtime.tonumber(val, base)];
  },
  tostring: function tostring(val) {
    return [runtime.tostring(val)];
  },
  type: function type(val) {
    return [runtime.type(val)];
  },
  unpack: function unpack(tab) {
    return tab;
  },
  xpcall: function xpcall() { throw new Error("TODO: Implement xpcall"); },
  inspect: function (val) {
    console.log(require('util').inspect(val, false, 10, true));
    return [];
  }
};
_G._G = _G;

return _G;

});
<|endoftext|>


<commit_before>'use strict';

(function (document, window) {
    document.addEventListener('DOMContentLoaded', function () {
        // Multi-checkbox required fix
        const form = document.getElementsByTagName('form');

        for (let a = 0; a < form.length; a++) {
            let sel = 'input[type=checkbox][multiple]';
            let multi = form[a].querySelectorAll(sel + '[required]');

            for (let b = 0; b < multi.length; b++) {
                multi[b].addEventListener('change', function () {
                    let req = !!this.form.querySelector(sel + '[name="' + this.name + '"]:checked');
                    let sib = this.form.querySelectorAll(sel + '[name="' + this.name + '"]');

                    for (let c = 0; c < sib.length; c++) {
                        if (req) {
                            sib[c].removeAttribute('required');
                        } else {
                            sib[c].setAttribute('required', 'required');
                        }
                    }
                });
            }
        }

        // Details
        const details = document.getElementsByTagName('details');

        if (details.length > 0) {
            if (typeof details[0].open === 'boolean') {
                const before = function () {
                    for (let a = 0; a < details.length; a++) {
                        details[a].setAttribute('open', '');
                    }
                };
                const after = function () {
                    for (let a = 0; a < details.length; a++) {
                        details[a].removeAttribute('open');
                    }
                };
                const mql = window.matchMedia('print');
                mql.addListener(function (media) {
                    if (media.matches) {
                        before();
                    } else {
                        after();
                    }
                });

                window.addEventListener('beforeprint', before);
                window.addEventListener('afterprint', after);
            } else {
                document.documentElement.setAttribute('data-shim-details', 'true');

                for (let a = 0; a < details.length; a++) {
                    // Define open property
                    Object.defineProperty(details[a], 'open', {
                        get: function () {
                            return this.hasAttribute('open');
                        },
                        set: function (state) {
                            if (state) {
                                this.setAttribute('open', '');
                            } else {
                                this.removeAttribute('open');
                            }
                        }
                    });

                    // Summary element
                    let summary = details[a].firstChild;

                    if (!summary || summary.tagName.toLowerCase() !== 'summary') {
                        summary = document.createElement('summary');
                        summary.innerText = 'Summary';
                        details[a].insertBefore(summary, details[a].firstChild);
                    }

                    summary.addEventListener('click', function () {
                        this.parentNode.open = !this.parentNode.hasAttribute('open');
                    });

                    // Wrap text nodes
                    let b = 0;
                    let child;

                    while (child = details[a].childNodes[b++]) {
                        if (child.nodeType === 3 && /[^\t\n\r ]/.test(child.data)) {
                            let span = document.createElement('span');
                            details[a].insertBefore(span, child);
                            span.textContent = child.data;
                            details[a].removeChild(child);
                        }
                    }
                }
            }
        }

        // Print version
        const print = document.querySelectorAll('span[data-act=print]');

        for (let a = 0; a < print.length; a++) {
            print[a].addEventListener('click', function () {
                window.print();
            });
        }
    });

    window.addEventListener('load', function () {
        // Sticky navigation polyfill
        const nav = document.getElementById('menu');

        if (!!nav && window.getComputedStyle(nav).getPropertyValue('position') !== 'sticky') {
            setTimeout(function() {
                const pos = nav.offsetTop;
                const width = window.getComputedStyle(nav.parentElement).getPropertyValue('width');

                window.addEventListener('scroll', function () {
                    if (window.pageYOffset >= pos) {
                        nav.setAttribute('data-sticky', '');
                        nav.style.width = width;
                    } else {
                        nav.removeAttribute('data-sticky');
                        nav.removeAttribute('style');
                    }
                });
            });
        }
    });
})(document, window);
<commit_msg>Refactor details polyfill/print handling<commit_after>'use strict';

(function (document, window) {
    function detailsBefore() {
        const details = document.getElementsByTagName('details');

        for (let a = 0; a < details.length; a++) {
            details[a].setAttribute('open', '');
        }
    }

    function detailsAfter() {
        const details = document.getElementsByTagName('details');

        for (let a = 0; a < details.length; a++) {
            details[a].removeAttribute('open');
        }
    }

    function detailsShim() {
        const details = document.getElementsByTagName('details');

        if (details.length <= 0 || typeof details[0].open === 'boolean') {
            return;
        }

        document.documentElement.setAttribute('data-shim-details', 'true');

        for (let a = 0; a < details.length; a++) {
            // Define open property
            Object.defineProperty(details[a], 'open', {
                get: function () {
                    return this.hasAttribute('open');
                },
                set: function (state) {
                    if (state) {
                        this.setAttribute('open', '');
                    } else {
                        this.removeAttribute('open');
                    }
                }
            });

            // Summary element
            let summary = details[a].firstChild;

            if (!summary || summary.tagName.toLowerCase() !== 'summary') {
                summary = document.createElement('summary');
                summary.innerText = 'Summary';
                details[a].insertBefore(summary, details[a].firstChild);
            }

            summary.addEventListener('click', function () {
                this.parentNode.open = !this.parentNode.hasAttribute('open');
            });

            // Wrap text nodes
            let b = 0;
            let child;

            while (child = details[a].childNodes[b++]) {
                if (child.nodeType === 3 && /[^\t\n\r ]/.test(child.data)) {
                    let span = document.createElement('span');
                    details[a].insertBefore(span, child);
                    span.textContent = child.data;
                    details[a].removeChild(child);
                }
            }
        }
    }

    document.addEventListener('DOMContentLoaded', function () {
        // Multi-checkbox required fix
        const form = document.getElementsByTagName('form');

        for (let a = 0; a < form.length; a++) {
            let sel = 'input[type=checkbox][multiple]';
            let multi = form[a].querySelectorAll(sel + '[required]');

            for (let b = 0; b < multi.length; b++) {
                multi[b].addEventListener('change', function () {
                    let req = !!this.form.querySelector(sel + '[name="' + this.name + '"]:checked');
                    let sib = this.form.querySelectorAll(sel + '[name="' + this.name + '"]');

                    for (let c = 0; c < sib.length; c++) {
                        if (req) {
                            sib[c].removeAttribute('required');
                        } else {
                            sib[c].setAttribute('required', 'required');
                        }
                    }
                });
            }
        }

        // Details
        detailsShim();

        const mql = window.matchMedia('print');
        mql.addListener(function (media) {
            if (media.matches) {
                detailsBefore();
            } else {
                detailsAfter();
            }
        });

        window.addEventListener('beforeprint', detailsBefore);
        window.addEventListener('afterprint', detailsAfter);

        // Print version
        const print = document.querySelectorAll('span[data-act=print]');

        for (let a = 0; a < print.length; a++) {
            print[a].addEventListener('click', function () {
                window.print();
            });
        }
    });

    window.addEventListener('load', function () {
        // Sticky navigation polyfill
        const nav = document.getElementById('menu');

        if (!!nav && window.getComputedStyle(nav).getPropertyValue('position') !== 'sticky') {
            setTimeout(function() {
                const pos = nav.offsetTop;
                const width = window.getComputedStyle(nav.parentElement).getPropertyValue('width');

                window.addEventListener('scroll', function () {
                    if (window.pageYOffset >= pos) {
                        nav.setAttribute('data-sticky', '');
                        nav.style.width = width;
                    } else {
                        nav.removeAttribute('data-sticky');
                        nav.removeAttribute('style');
                    }
                });
            });
        }
    });
})(document, window);
<|endoftext|>


<commit_before>// type testing utility functions

;(function($$, window){ 'use strict';

  $$.is = {
    defined: function(obj){
      return obj != null; // not undefined or null
    },

    string: function(obj){
      return obj != null && typeof obj == typeof '';
    },

    fn: function(obj){
      return obj != null && typeof obj === typeof function(){};
    },

    array: function(obj){
      return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;
    },

    plainObject: function(obj){
      return obj != null && typeof obj === typeof {} && !$$.is.array(obj) && obj.constructor === Object;
    },

    number: function(obj){
      return obj != null && typeof obj === typeof 1 && !isNaN(obj);
    },

    integer: function( obj ){
      return $$.is.number(obj) && Math.floor(obj) === obj;
    },

    color: function(obj){
      return obj != null && typeof obj === typeof '' && $.Color(obj).toString() !== '';
    },

    bool: function(obj){
      return obj != null && typeof obj === typeof true;
    },

    elementOrCollection: function(obj){
      return $$.is.element(obj) || $$.is.collection(obj);
    },

    element: function(obj){
      return obj instanceof $$.Element && obj._private.single;
    },

    collection: function(obj){
      return obj instanceof $$.Collection && !obj._private.single;
    },

    core: function(obj){
      return obj instanceof $$.Core;
    },

    style: function(obj){
      return obj instanceof $$.Style;
    },

    stylesheet: function(obj){
      return obj instanceof $$.Stylesheet;
    },

    event: function(obj){
      return obj instanceof $$.Event;
    },

    emptyString: function(obj){
      if( !obj ){ // null is empty
        return true;
      } else if( $$.is.string(obj) ){
        if( obj === '' || obj.match(/^\s+$/) ){
          return true; // empty string is empty
        }
      }

      return false; // otherwise, we don't know what we've got
    },

    nonemptyString: function(obj){
      if( obj && $$.is.string(obj) && obj !== '' && !obj.match(/^\s+$/) ){
        return true;
      }

      return false;
    },

    domElement: function(obj){
      if( typeof HTMLElement === 'undefined' ){
        return false; // we're not in a browser so it doesn't matter
      } else {
        return obj instanceof HTMLElement;
      }
    },

    touch: function(){
      return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch );
    },

    boundingBox: function(obj){
      return $$.is.plainObject(obj) &&
        $$.is.number(obj.x1) && $$.is.number(obj.x2) &&
        $$.is.number(obj.y1) && $$.is.number(obj.y2)
      ;
    }
  };

})( cytoscape, typeof window === 'undefined' ? null : window );
<commit_msg>add engine detection for minor workarounds etc<commit_after>// type testing utility functions

;(function($$, window){ 'use strict';

  $$.is = {
    defined: function(obj){
      return obj != null; // not undefined or null
    },

    string: function(obj){
      return obj != null && typeof obj == typeof '';
    },

    fn: function(obj){
      return obj != null && typeof obj === typeof function(){};
    },

    array: function(obj){
      return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;
    },

    plainObject: function(obj){
      return obj != null && typeof obj === typeof {} && !$$.is.array(obj) && obj.constructor === Object;
    },

    number: function(obj){
      return obj != null && typeof obj === typeof 1 && !isNaN(obj);
    },

    integer: function( obj ){
      return $$.is.number(obj) && Math.floor(obj) === obj;
    },

    color: function(obj){
      return obj != null && typeof obj === typeof '' && $.Color(obj).toString() !== '';
    },

    bool: function(obj){
      return obj != null && typeof obj === typeof true;
    },

    elementOrCollection: function(obj){
      return $$.is.element(obj) || $$.is.collection(obj);
    },

    element: function(obj){
      return obj instanceof $$.Element && obj._private.single;
    },

    collection: function(obj){
      return obj instanceof $$.Collection && !obj._private.single;
    },

    core: function(obj){
      return obj instanceof $$.Core;
    },

    style: function(obj){
      return obj instanceof $$.Style;
    },

    stylesheet: function(obj){
      return obj instanceof $$.Stylesheet;
    },

    event: function(obj){
      return obj instanceof $$.Event;
    },

    emptyString: function(obj){
      if( !obj ){ // null is empty
        return true;
      } else if( $$.is.string(obj) ){
        if( obj === '' || obj.match(/^\s+$/) ){
          return true; // empty string is empty
        }
      }

      return false; // otherwise, we don't know what we've got
    },

    nonemptyString: function(obj){
      if( obj && $$.is.string(obj) && obj !== '' && !obj.match(/^\s+$/) ){
        return true;
      }

      return false;
    },

    domElement: function(obj){
      if( typeof HTMLElement === 'undefined' ){
        return false; // we're not in a browser so it doesn't matter
      } else {
        return obj instanceof HTMLElement;
      }
    },

    boundingBox: function(obj){
      return $$.is.plainObject(obj) &&
        $$.is.number(obj.x1) && $$.is.number(obj.x2) &&
        $$.is.number(obj.y1) && $$.is.number(obj.y2)
      ;
    },

    touch: function(){
      return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch );
    },

    moz: function(){
      return typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style);
    },

    webkit: function(){
      return typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style);
    },

    chrome: function(){
      return typeof chrome !== 'undefined';
    },

    khtml: function(){
      return navigator.vendor.match(/kde/i); // TODO probably a better way to detect this...
    },

    khtmlEtc: function(){
      return $$.is.khtml() || $$.is.webkit() || $$.is.blink();
    },

    ms: function(){
      return typeof ActiveXObject !== 'undefined' || /*@cc_on!@*/false;
    }
  };

})( cytoscape, typeof window === 'undefined' ? null : window );
<|endoftext|>


<commit_before>(function (exports) {
    "use strict";

    /*global d3 */

 // Draws a heatmap.
 // @param {object} data
 // @param {object} options
 // @param {DOMElement} options.parentElement Parent element of the SVG element.
 // @param {number} options.width Width of the SVG element.
 // @param {number} options.height Height of the SVG element.
    exports.heatmap = function (data, options) {

        var parentElement, width, height, colorScale, numRects, rectWidth, rectHeight, svg;

     // Evaluate options and set defaults.
        options = options || {};
        parentElement = options.parentElement || document.body;
        width = options.width || 300;
        height = options.height || 300;

     // Create padded scale for the x axis.
        colorScale = d3.scale.linear()
                       .domain([-1, 0, 1])
                       .range(["green", "black", "red"]);

     // Capture the basics.
        numRects = Object.keys(data).length;
        rectWidth = width / numRects;
        rectHeight = height / numRects;

     // Set up the SVG element.
        svg = d3.select(parentElement)
                .append("svg:svg")
                .attr("width", width)
                .attr("height", height);

     // Prepare data.
        Object.keys(data).forEach(function (rowLabel, rowIndex) {
            var columnLabels, row;
            columnLabels = Object.keys(data[rowLabel]);
            row = [];
            columnLabels.forEach(function (columnLabel) {
                row.push(data[rowLabel][columnLabel]);
            });
         // Generate and append rectangles.
            svg.append("svg:g")
               .selectAll("rect")
               .data(row)
               .enter()
               .append("rect")
               .attr("x", function (d, columnIndex) {
                   return columnIndex * rectWidth;
                })
               .attr("y", function () {
                   return rowIndex * rectWidth;
                })
               .attr("width", rectWidth)
               .attr("height", rectHeight)
               .attr("fill", colorScale)
               .append("svg:title")
               .text(function (d, i) {
                    return rowLabel + "  and  " + columnLabels[i];
                });
        });

    };

}(window));
<commit_msg>Improve tooltips.<commit_after>(function (exports) {
    "use strict";

    /*global d3 */

 // Draws a heatmap.
 // @param {object} data
 // @param {object} options
 // @param {DOMElement} options.parentElement Parent element of the SVG element.
 // @param {number} options.width Width of the SVG element.
 // @param {number} options.height Height of the SVG element.
    exports.heatmap = function (data, options) {

        var parentElement, width, height, tooltip, colorScale, numRects, rectWidth, rectHeight, svg;

     // Evaluate options and set defaults.
        options = options || {};
        parentElement = options.parentElement || document.body;
        width = options.width || 300;
        height = options.height || 300;
        tooltip = options.tooltip || (function () {
            var body, tooltip;
            body = d3.select("body");
            tooltip = body.append("div")
                          .style("display", "none")
                          .style("position", "absolute")
                          .style("padding", "5px")
                          .style("background-color", "rgba(242, 242, 242, .6)");
            return {
                show: function (d) {
                    var mouse;
                    mouse = d3.mouse(body.node());
                    tooltip.style("display", null)
                           .style("left", (mouse[0] + 25) + "px")
                           .style("top", (mouse[1] - 10) + "px")
                           .html(d);
                },
                hide: function () {
                    tooltip.style("display", "none");
                }
            };
        }());

     // Create padded scale for the x axis.
        colorScale = d3.scale.linear()
                       .domain([-1, 0, 1])
                       .range(["green", "black", "red"]);

     // Capture the basics.
        numRects = Object.keys(data).length;
        rectWidth = width / numRects;
        rectHeight = height / numRects;

     // Set up the SVG element.
        svg = d3.select(parentElement)
                .append("svg:svg")
                .attr("width", width)
                .attr("height", height);

     // Prepare data.
        Object.keys(data).forEach(function (rowLabel, rowIndex) {
            var columnLabels, row;
            columnLabels = Object.keys(data[rowLabel]);
            row = [];
            columnLabels.forEach(function (columnLabel) {
                row.push(data[rowLabel][columnLabel]);
            });
         // Generate and append rectangles.
            svg.append("svg:g")
               .selectAll("rect")
               .data(row)
               .enter()
               .append("rect")
               .attr("x", function (d, columnIndex) {
                   return columnIndex * rectWidth;
                })
               .attr("y", function () {
                   return rowIndex * rectWidth;
                })
               .attr("width", rectWidth)
               .attr("height", rectHeight)
               .attr("fill", colorScale)
               .on("mousemove", function (d, i) {
                   tooltip.show(rowLabel + " and " + columnLabels[i] + ":<br>" + d);
                })
               .on("mouseout", function (d) {
                   tooltip.hide();
                });
        });

    };

}(window));
<|endoftext|>


<commit_before>/*
 *  helpers.js
 *
 *  David Janes
 *  IOTDB.org
 *  2013-12-01
 *
 *  Nodejs IOTDB control
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var crypto = require('crypto');
var node_url = require('url');
var path = require('path');

exports.underscore = require('underscore')

var modules = [
    exports.underscore,
    require('./helpers/ld'),
    require('./helpers/id'),
    require('./helpers/d'),
    require('./helpers/hash'),
    require('./helpers/is'),
    require('./helpers/net'),
    require('./helpers/color'),
    require('./helpers/timestamp'),
    require('./helpers/error'),
    require('./helpers/convert'),
];
for (var mi in modules) {
    var module = modules[mi];
    for (var key in module) {
        exports[key] = module[key];
    }
}

// prefer '_.color.Color', this is for backwards compat
exports.Color = exports.color.Color;

exports.temperature = require("./helpers/temperature").temperature;

var _queued = {};
exports.Queue = require('./queue').FIFOQueue;
exports.queue = function (name) {
    var queue = _queued[name];
    if (!queue) {
        queue = new exports.Queue(name);
        _queued[name] = queue
    }

    return queue;
}

exports.bridge_wrapper = require('./bridge_wrapper').bridge_wrapper;

/**
 *  @module helpers
 */

// Establish the object that gets returned to break out of a loop iteration.
var breaker = {};

// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype,
    ObjProto = Object.prototype,
    FuncProto = Function.prototype;

//use the faster Date.now if available.
var getTime = (Date.now || function () {
    return new Date().getTime();
});

// Create quick reference variables for speed access to core prototypes.
var
    push = ArrayProto.push,
    slice = ArrayProto.slice,
    concat = ArrayProto.concat,
    toString = ObjProto.toString,
    hasOwnProperty = ObjProto.hasOwnProperty;

// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var
    nativeForEach = ArrayProto.forEach,
    nativeMap = ArrayProto.map,
    nativeReduce = ArrayProto.reduce,
    nativeReduceRight = ArrayProto.reduceRight,
    nativeFilter = ArrayProto.filter,
    nativeEvery = ArrayProto.every,
    nativeSome = ArrayProto.some,
    nativeIndexOf = ArrayProto.indexOf,
    nativeLastIndexOf = ArrayProto.lastIndexOf,
    nativeIsArray = Array.isArray,
    nativeKeys = Object.keys,
    nativeBind = FuncProto.bind;

// Collection Functions
// --------------------

// The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = exports.each = exports.forEach = function (obj, iterator, context) {
    if (obj == null) return;
    if (nativeForEach && obj.forEach === nativeForEach) {
        obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
        for (var i = 0, length = obj.length; i < length; i++) {
            if (iterator.call(context, obj[i], i, obj) === breaker) return;
        }
    } else {
        var keys = exports.keys(obj);
        for (var i = 0, length = keys.length; i < length; i++) {
            if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
        }
    }
};

// Create a (shallow-cloned) duplicate of an object.
exports.clone = function (obj) {
    if (!exports.isObject(obj)) return obj;
    return exports.isArray(obj) ? obj.slice() : exports.extend({}, obj);
};

// Invokes interceptor with the obj, and then returns obj.
// The primary purpose of this method is to "tap into" a method chain, in
// order to perform operations on intermediate results within the chain.
exports.tap = function (obj, interceptor) {
    interceptor(obj);
    return obj;
};

// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
exports.has = function (obj, key) {
    return hasOwnProperty.call(obj, key);
};

/*
 *  The next three functions courtesy
 *  http://geniuscarrier.com/copy-object-in-javascript/
 */
exports.shallowCopy = function (oldObj) {
    var newObj = {};
    for (var i in oldObj) {
        if (oldObj.hasOwnProperty(i)) {
            newObj[i] = oldObj[i];
        }
    }
    return newObj;
};

exports.deepCopy = function (oldObj) {
    var newObj = oldObj;
    if (oldObj && typeof oldObj === 'object') {
        newObj = Object.prototype.toString.call(oldObj) === "[object Array]" ? [] : {};
        for (var i in oldObj) {
            newObj[i] = exports.deepCopy(oldObj[i]);
        }
    }
    return newObj;
};

exports.mix = function () {
    var i, j, newObj = {};
    for (i = 0; i < arguments.length; i++) {
        for (j in arguments[i]) {
            if (arguments[i].hasOwnProperty(j)) {
                newObj[j] = arguments[i][j];
            }
        }
    }
    return newObj;
};

/**
 *  Return the proper keys of a dictionary
 */
exports.keys = function (d) {
    var keys = [];

    for (var key in d) {
        if (d.hasOwnProperty(key)) {
            keys.push(key);
        }
    }

    return keys;
};

/**
 *  Return true iff everthing a === b, in a deep
 *  and "pythonic" sense
 */
exports.equals = function (a, b) {
    return exports.isEqual(a, b);
};

/* --- random stuff --- */
exports.randint = function (n) {
    return Math.floor(Math.random() * n);
};

exports.choose = function (vs) {
    return vs[exports.randint(vs.length)];
};

/**
 *  Make sure a 'paramd' is properly set up. That is,
 *  that it's a dictionary and if any values in defaultd
 *  are undefined in paramd, they're copied over
 *
 *  @param {dictionary|undefined} paramd
 *  The paramd passed in to the function calling this.
 *  Often undefined
 *
 *  @param {dictionary} defaultd
 *  What the values should be
 *
 *  @param {dictionary}
 *  The paramd to use, not necessarily the one passed in
 */
exports.defaults = function (paramd) {
    if (!paramd) {
        paramd = {}
    }

    each(slice.call(arguments, 1), function (defaultd) {
        for (var key in defaultd) {
            var pvalue = paramd[key]
            if (pvalue === undefined) {
                paramd[key] = defaultd[key]
            }
        }
    });

    return paramd;
};

/**
 *  Django(-ish) string formatting. Can take
 *  multiple dictionaries as arguments, priority
 *  given to the first argument seen
 *

 *  The first argument can be JSON-like objects,
 *  in which case we'll run this recursively
 */
exports.format = function () {
    if (arguments.length == 0) {
        throw "format requires at least one argument"
    }

    var template = arguments[0]

    var valueds = []
    for (var ai = 1; ai < arguments.length; ai++) {
        valueds.push(arguments[ai])
    }

    return _format(template, valueds)
};

var _format = function (template, valueds) {
    if (exports.isArray(template)) {
        var ns = []
        var os = template
        for (var oi = 0; oi < os.length; oi++) {
            var o = os[oi]
            var n = _format(o, valueds)
            ns.append(ns)
        }
    } else if (exports.isObject(template)) {
        var nd = {}
        var od = template
        for (var key in od) {
            var ovalue = od[key]
            var nvalue = _format(ovalue, valueds)
            nd[key] = nvalue
        }

        return nd
    } else if (!exports.isString(template)) {
        return template
    } else {
        return template.replace(/{{(.*?)}}/g, function (match, variable) {
            var otherwise = ""

            // we can layer in django "|" later
            var colonx = variable.indexOf(':')
            if (colonx > -1) {
                otherwise = variable.substring(colonx + 1)
                variable = variable.substring(0, colonx)
            }

            var parts = variable.replace(/ /g, '').split('.')

            var found = false;

            for (var vdi = 0; vdi < valueds.length; vdi++) {
                var valued = valueds[vdi];
                for (var pi = 0; pi < parts.length - 1; pi++) {
                    var part = parts[pi];
                    var subd = valued[part];
                    if (!exports.isObject(subd)) {
                        break;
                    }

                    valued = subd
                }

                var value = valued[parts[parts.length - 1]]
                if (value !== undefined) {
                    return "" + value
                }
            }

            return otherwise
        })

        return template
    }
};

/**
 */
exports.uid = function (len) {
    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    var buf = [],
        chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
        charlen = chars.length;

    for (var i = 0; i < len; ++i) {
        buf.push(chars[getRandomInt(0, charlen - 1)]);
    }

    return buf.join('');
};

var oneofd = {};
exports.oneof = function (module) {
    var m = oneofd[module];
    if (m === undefined) {
        m = require(module);
        if (module === 'seneca') { // HACK!
            m = m();
        }
        oneofd[module] = m;
    }

    return m;
};

exports.noop = function() {};
<commit_msg>cleanup<commit_after>/*
 *  helpers.js
 *
 *  David Janes
 *  IOTDB.org
 *  2013-12-01
 *
 *  Nodejs IOTDB control
 *
 *  Copyright [2013-2016] [David P. Janes]
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

"use strict";

var crypto = require('crypto');
var node_url = require('url');
var path = require('path');

exports.underscore = require('underscore')

var modules = [
    exports.underscore,
    require('./helpers/ld'),
    require('./helpers/id'),
    require('./helpers/d'),
    require('./helpers/hash'),
    require('./helpers/is'),
    require('./helpers/net'),
    require('./helpers/color'),
    require('./helpers/timestamp'),
    require('./helpers/error'),
    require('./helpers/convert'),
];
for (var mi in modules) {
    var module = modules[mi];
    for (var key in module) {
        exports[key] = module[key];
    }
}

// prefer '_.color.Color', this is for backwards compat
exports.Color = exports.color.Color;

exports.temperature = require("./helpers/temperature").temperature;

var _queued = {};
exports.Queue = require('./queue').FIFOQueue;
exports.queue = function (name) {
    var queue = _queued[name];
    if (!queue) {
        queue = new exports.Queue(name);
        _queued[name] = queue
    }

    return queue;
}

exports.bridge_wrapper = require('./bridge_wrapper').bridge_wrapper;

/**
 *  @module helpers
 */

// Establish the object that gets returned to break out of a loop iteration.
var breaker = {};

// Save bytes in the minified (but not gzipped) version:
var ArrayProto = Array.prototype,
    ObjProto = Object.prototype,
    FuncProto = Function.prototype;

//use the faster Date.now if available.
var getTime = (Date.now || function () {
    return new Date().getTime();
});

// Create quick reference variables for speed access to core prototypes.
var
    push = ArrayProto.push,
    slice = ArrayProto.slice,
    concat = ArrayProto.concat,
    toString = ObjProto.toString,
    hasOwnProperty = ObjProto.hasOwnProperty;

// All **ECMAScript 5** native function implementations that we hope to use
// are declared here.
var
    nativeForEach = ArrayProto.forEach,
    nativeMap = ArrayProto.map,
    nativeReduce = ArrayProto.reduce,
    nativeReduceRight = ArrayProto.reduceRight,
    nativeFilter = ArrayProto.filter,
    nativeEvery = ArrayProto.every,
    nativeSome = ArrayProto.some,
    nativeIndexOf = ArrayProto.indexOf,
    nativeLastIndexOf = ArrayProto.lastIndexOf,
    nativeIsArray = Array.isArray,
    nativeKeys = Object.keys,
    nativeBind = FuncProto.bind;

// Collection Functions
// --------------------

// The cornerstone, an `each` implementation, aka `forEach`.
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = exports.each = exports.forEach = function (obj, iterator, context) {
    if (obj == null) return;
    if (nativeForEach && obj.forEach === nativeForEach) {
        obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
        for (var i = 0, length = obj.length; i < length; i++) {
            if (iterator.call(context, obj[i], i, obj) === breaker) return;
        }
    } else {
        var keys = exports.keys(obj);
        for (var i = 0, length = keys.length; i < length; i++) {
            if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
        }
    }
};

// Create a (shallow-cloned) duplicate of an object.
exports.clone = function (obj) {
    if (!exports.isObject(obj)) return obj;
    return exports.isArray(obj) ? obj.slice() : exports.extend({}, obj);
};

// Invokes interceptor with the obj, and then returns obj.
// The primary purpose of this method is to "tap into" a method chain, in
// order to perform operations on intermediate results within the chain.
exports.tap = function (obj, interceptor) {
    interceptor(obj);
    return obj;
};

// Shortcut function for checking if an object has a given property directly
// on itself (in other words, not on a prototype).
exports.has = function (obj, key) {
    return hasOwnProperty.call(obj, key);
};

/*
 *  The next three functions courtesy
 *  http://geniuscarrier.com/copy-object-in-javascript/
 */
exports.shallowCopy = function (oldObj) {
    var newObj = {};
    for (var i in oldObj) {
        if (oldObj.hasOwnProperty(i)) {
            newObj[i] = oldObj[i];
        }
    }
    return newObj;
};

exports.deepCopy = function (oldObj) {
    var newObj = oldObj;
    if (oldObj && typeof oldObj === 'object') {
        newObj = Object.prototype.toString.call(oldObj) === "[object Array]" ? [] : {};
        for (var i in oldObj) {
            newObj[i] = exports.deepCopy(oldObj[i]);
        }
    }
    return newObj;
};

exports.mix = function () {
    var i, j, newObj = {};
    for (i = 0; i < arguments.length; i++) {
        for (j in arguments[i]) {
            if (arguments[i].hasOwnProperty(j)) {
                newObj[j] = arguments[i][j];
            }
        }
    }
    return newObj;
};

/**
 *  Return the proper keys of a dictionary
 */
exports.keys = function (d) {
    var keys = [];

    for (var key in d) {
        if (d.hasOwnProperty(key)) {
            keys.push(key);
        }
    }

    return keys;
};

/**
 *  Return true iff everthing a === b, in a deep
 *  and "pythonic" sense
 */
exports.equals = function (a, b) {
    return exports.isEqual(a, b);
};

/* --- random stuff --- */
exports.randint = function (n) {
    return Math.floor(Math.random() * n);
};

exports.choose = function (vs) {
    return vs[exports.randint(vs.length)];
};

/**
 *  Make sure a 'paramd' is properly set up. That is,
 *  that it's a dictionary and if any values in defaultd
 *  are undefined in paramd, they're copied over
 *
 *  @param {dictionary|undefined} paramd
 *  The paramd passed in to the function calling this.
 *  Often undefined
 *
 *  @param {dictionary} defaultd
 *  What the values should be
 *
 *  @param {dictionary}
 *  The paramd to use, not necessarily the one passed in
 */
exports.defaults = function (paramd) {
    if (!paramd) {
        paramd = {}
    }

    each(slice.call(arguments, 1), function (defaultd) {
        for (var key in defaultd) {
            var pvalue = paramd[key]
            if (pvalue === undefined) {
                paramd[key] = defaultd[key]
            }
        }
    });

    return paramd;
};

/**
 *  Django(-ish) string formatting. Can take
 *  multiple dictionaries as arguments, priority
 *  given to the first argument seen
 *

 *  The first argument can be JSON-like objects,
 *  in which case we'll run this recursively
 */
exports.format = function () {
    if (arguments.length == 0) {
        throw "format requires at least one argument"
    }

    var template = arguments[0]

    var valueds = []
    for (var ai = 1; ai < arguments.length; ai++) {
        valueds.push(arguments[ai])
    }

    return _format(template, valueds)
};

var _format = function (template, valueds) {
    if (exports.isArray(template)) {
        var ns = []
        var os = template
        for (var oi = 0; oi < os.length; oi++) {
            var o = os[oi]
            var n = _format(o, valueds)
            ns.append(ns)
        }
    } else if (exports.isObject(template)) {
        var nd = {}
        var od = template
        for (var key in od) {
            var ovalue = od[key]
            var nvalue = _format(ovalue, valueds)
            nd[key] = nvalue
        }

        return nd
    } else if (!exports.isString(template)) {
        return template
    } else {
        return template.replace(/{{(.*?)}}/g, function (match, variable) {
            var otherwise = ""

            // we can layer in django "|" later
            var colonx = variable.indexOf(':')
            if (colonx > -1) {
                otherwise = variable.substring(colonx + 1)
                variable = variable.substring(0, colonx)
            }

            var parts = variable.replace(/ /g, '').split('.')

            var found = false;

            for (var vdi = 0; vdi < valueds.length; vdi++) {
                var valued = valueds[vdi];
                for (var pi = 0; pi < parts.length - 1; pi++) {
                    var part = parts[pi];
                    var subd = valued[part];
                    if (!exports.isObject(subd)) {
                        break;
                    }

                    valued = subd
                }

                var value = valued[parts[parts.length - 1]]
                if (value !== undefined) {
                    return "" + value
                }
            }

            return otherwise
        })

        return template
    }
};

/**
 */
exports.uid = function (len) {
    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    var buf = [],
        chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
        charlen = chars.length;

    for (var i = 0; i < len; ++i) {
        buf.push(chars[getRandomInt(0, charlen - 1)]);
    }

    return buf.join('');
};

var oneofd = {};
exports.oneof = function (module) {
    var m = oneofd[module];
    if (m === undefined) {
        m = require(module);
        if (module === 'seneca') { // HACK!
            m = m();
        }
        oneofd[module] = m;
    }

    return m;
};

exports.noop = function () {};
<|endoftext|>


<commit_before>var connsSparql = ([
"SELECT ?email ?lat ?long ?strength",
"WHERE{",
"  ?school <http://www.w3.org/2006/vcard/ns#hasEmail> ?email.",
"  ?school <http://data.ordnancesurvey.co.uk/ontology/postcode/postcode> ?pc.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?slat.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?slong.",
"  ?zone <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?lat.",
"  ?zone <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?long.",
"  ?nop <http://data.opendatascotland.org/def/education/numberOfPupils> ?strength.",
"  ?nop <http://data.opendatascotland.org/def/statistical-dimensions/education/school> ?school.",
"  ?nop <http://data.opendatascotland.org/def/statistical-dimensions/refArea> ?zone.",
"  ?school <http://data.opendatascotland.org/def/education/department> ?dep.",
"  ?dep <http://data.opendatascotland.org/def/education/stageOfEducation> <http://data.opendatascotland.org/def/concept/education/stages-of-education/%{stage}>.",
"}",
"ORDER BY ?email"]).join("\n");

var schoolsSparql = ([
"SELECT ?email ?lat ?long (SUM (?nop) as ?size) ?name",
"WHERE{",
"  ?school <http://data.ordnancesurvey.co.uk/ontology/postcode/postcode> ?pc.",
"  ?school <http://www.w3.org/2006/vcard/ns#hasEmail> ?email.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?lat.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?long.",
"  OPTIONAL{",
"    ?school <http://www.w3.org/2000/01/rdf-schema#label> ?name",
"  }",
"  GRAPH <http://data.opendatascotland.org/graph/education/pupils-by-school-and-datazone>{",
"    ?x <http://data.opendatascotland.org/def/statistical-dimensions/education/school> ?school.",
"    ?x <http://data.opendatascotland.org/def/education/numberOfPupils> ?nop.",
"  }",
"  ?school <http://data.opendatascotland.org/def/education/department> ?dep.",
"  ?dep <http://data.opendatascotland.org/def/education/stageOfEducation> <http://data.opendatascotland.org/def/concept/education/stages-of-education/%{stage}>.",
"}",
"GROUP BY ?email ?lat ?long ?size ?name",
"ORDER BY ?email"]).join("\n");

var schools = {};

var DEBUG = true;

// schoolType one of "secondary", "primary", "pre-school"
//do not call directly, called from "redraw()"
function requestData(schoolType){
  clean();
  var schoolsUrl = "http://data.opendatascotland.org/sparql.json?query=" +
    encodeURIComponent(schoolsSparql) + "&stage=" +
    encodeURIComponent(schoolType);
  $.ajax({
    dataType: 'text',
    url: schoolsUrl,
    success: function(data){
      data = JSON.parse(data).results.bindings;
      for(var i = 0; i < data.length - 1; i++){
        schools[data[i].email.value] = {
          'email': data[i].email.value,
          'name': data[i].name ? data[i].name.value : null,
          'latLong': new google.maps.LatLng(parseFloat(data[i].lat.value),
              parseFloat(data[i].long.value)),
          'size': parseInt(data[i].size.value),
          'conns': []
        };
      }
      requestConnData(schoolType, 1);
    }
  });
}

function requestConnData(schoolType, page){
  var connsUrl = "http://data.opendatascotland.org/sparql.json?query=" +
    encodeURIComponent(connsSparql) + "&stage=" +
    encodeURIComponent(schoolType) + "&per_page=10000&page=" + page;
  $.ajax({
    dataType: 'text',
    url: connsUrl,
    success: function(data){
      var found = false;
      data = JSON.parse(data).results.bindings;
      if(data.length != 0)
        found = true;
      for(var i = 0; i < data.length - 1; i++){
        if(!(data[i].email.value in schools))
          continue;
        schools[data[i].email.value].conns.push({
          'latLong': new google.maps.LatLng(parseFloat(data[i].lat.value),
              parseFloat(data[i].long.value)),
          'strength': parseInt(data[i].strength.value)
        });
      }
      if(found){
        requestConnData(schoolType, page + 1);
      }
      else{
        flattenSchools();
        drawConns();
        drawSchools();
      }
    }
  });
}

function flattenSchools(){
  var arr = [];
  for(var key in schools){
    arr.push(schools[key]);
  }
  schools = arr;
}

//boolean values as objects so that they are mutable form inside the button listener
var showingPreSchools = {value: false};
var showingPrimarySchools = {value: false};
var showingSecondarySchools = {value: true};

//TODO make redraw hide and show objects rather than re-calling the database.
function redraw() {
  clean(); //remove everything

  if(DEBUG) {
	console.log("Showing Pre-Schools: " + showingPreSchools.value);
	console.log("Showing Primary Schools: " + showingPrimarySchools.value);
	console.log("Showing Secondary Schools: " + showingSecondarySchools.value);
  }

  if(showingPreSchools.value) { //if supposed to be drawing; draw.
    requestData("pre-school");
  }

  if(showingPrimarySchools.value) {
    requestData("primary");
  }

  if(showingSecondarySchools.value) {
    requestData("secondary");
  }
}

redraw();

//removed all currently drawing map objects.
function clean() {
  for(var i = 0; i < schools.length; i++){
    schools[i].ui.circle.setMap(null);
    schools[i].ui.infowindow.close();
    for(var j = 0; j < schools[i].conns.length; j++){
      var conn = schools[i].conns[j];
      if(conn.ui)
        schools[i].conns[j].ui.setMap(null);
    }
  }
  schools = [];
}

function drawSchools(data){
var totStudents = 0;
  for(var i = 0; i < schools.length; i++){
    drawSchool(schools[i]);
  }
}

function drawConns(data){
  for(var i = 0; i < schools.length; i++){
    for(var j = 0; j < schools[i].conns.length; j++){
      var conn = schools[i].conns[j];
      if(conn.strength < 10)
        continue;
      drawPath(schools[i], conn);
    }
  }
}

function drawZone(map, zoneLatLong){
  drawPoint //what this? //
}

function drawArrow(map, zoneLatLong, schoolLatLong) {}

var map;

var mapStyles = [ { "featureType": "poi", "stylers": [ { "weight": 1.9 }, { "visibility": "off" } ] },{ "featureType": "poi.school", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.man_made", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.natural", "stylers": [ { "visibility": "off" } ] } ] ;

function initialize() {
  var centerLatlng = new google.maps.LatLng(56.632064,-3.729858);
  var mapOptions = {
    zoom: 7,
	disableDefaultUI: true,
    center: centerLatlng ,
    mapTypeControlOptions: {
        mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
      }
  }

  var mapDiv = document.getElementById('map-canvas');
  map = new google.maps.Map(mapDiv, mapOptions);

  map.setOptions({styles : mapStyles})

  var defStyle = [{}]

  var styledMap = new google.maps.StyledMapType(defStyle, {name: "Default"});
  map.mapTypes.set('map_style', styledMap);
  map.setMapTypeId('map_style');

  button(" Pre-", showingPreSchools);
  button(" Primary ", showingPrimarySchools);
  button(" Secondary ", showingSecondarySchools);
}

function button(type, bool) {
  var homeControlDiv = document.createElement('div');
  var bc = new buttonControl(homeControlDiv, type, bool);
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(homeControlDiv);
}

function buttonControl(controlDiv, type, bool) {
  var startDrawing = "Show" + type + "Schools";
  var stopDrawing = "Hide" + type + "Schools";
  var info = "Toggle" + type + "Schools";
  var showColor = "green";
  var hideColor = "red";

  controlDiv.style.padding = '5px';

  var controlUI = document.createElement('div');
  controlUI.style.backgroundColor = bool.value ? hideColor : showColor;
  controlUI.style.width = '160px';
  controlUI.style.borderStyle = 'solid';
  controlUI.style.borderWidth = '2px';
  controlUI.style.cursor = 'pointer';
  controlUI.style.textAlign = 'center';
  controlUI.title = info;
  controlDiv.appendChild(controlUI);

  var controlText = document.createElement('div');
  controlText.style.fontFamily = 'Arial,sans-serif';
  controlText.style.fontSize = '12px';
  controlText.style.paddingLeft = '4px';
  controlText.style.paddingRight = '4px';
  controlText.innerHTML = bool.value ? stopDrawing : startDrawing;
  controlUI.appendChild(controlText);

  google.maps.event.addDomListener(controlUI, 'click', function() {
	bool.value = !bool.value; //toggle the drawing state

    if(bool.value) { //if drawing
	  controlText.innerHTML = stopDrawing; //set button text to "stop drawing"
      controlUI.style.backgroundColor = hideColor;
	} else {
	  controlText.innerHTML = startDrawing; // set button text to "draw"
	  controlUI.style.backgroundColor = showColor;
	}
	redraw(); //redraw all the schools
  });
}

function drawPath(LatSchool, LongSchool, LatDataZone, LongDataZone) {
  drawPath(map, new google.maps.LatLng(LatSchool, LongSchool),
			new google.maps.LatLng(LatDataZone, LongDataZone)
  );
}

function drawPath(school, conn) {
  var options = {
    path: [conn.latLong, school.latLong],
    strokeOpacity: Math.min(1.0, (Math.log(conn.strength) - 2) / 2),
    strokeWeight: 1.0,
    icons: [{
      offset: '100%'
    }],
    map: map
  };

  conn.ui = new google.maps.Polyline(options);
}

function drawSchool(school) {
  var options = {
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.25,
    map: map,
    center: school.latLong,
    radius: (school.size * 0.5)
  };

  var circ = new google.maps.Circle(options);
  school.ui = {
    'circle': circ,
    'infowindow': new google.maps.InfoWindow({
      content: '
' + school.name + '

' + "Students: " + school.size +  '
',
      position: circ.center
    })
  }

  google.maps.event.addListener(school.ui.circle, 'mouseover', function() {
    if (map.getZoom() > 8) {
      school.ui.infowindow.open(map) }
  });

  google.maps.event.addListener(school.ui.circle, 'mouseout', function() {
    school.ui.infowindow.close();
  });
}

//on load, run initialize
google.maps.event.addDomListener(window, 'load', initialize);

<commit_msg>Repaired show options<commit_after>var connsSparql = ([
"SELECT ?email ?lat ?long ?strength",
"WHERE{",
"  ?school <http://www.w3.org/2006/vcard/ns#hasEmail> ?email.",
"  ?school <http://data.ordnancesurvey.co.uk/ontology/postcode/postcode> ?pc.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?slat.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?slong.",
"  ?zone <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?lat.",
"  ?zone <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?long.",
"  ?nop <http://data.opendatascotland.org/def/education/numberOfPupils> ?strength.",
"  ?nop <http://data.opendatascotland.org/def/statistical-dimensions/education/school> ?school.",
"  ?nop <http://data.opendatascotland.org/def/statistical-dimensions/refArea> ?zone.",
"  ?school <http://data.opendatascotland.org/def/education/department> ?dep.",
"  ?dep <http://data.opendatascotland.org/def/education/stageOfEducation> <http://data.opendatascotland.org/def/concept/education/stages-of-education/%{stage}>.",
"}",
"ORDER BY ?email"]).join("\n");

var schoolsSparql = ([
"SELECT ?email ?lat ?long (SUM (?nop) as ?size) ?name",
"WHERE{",
"  ?school <http://data.ordnancesurvey.co.uk/ontology/postcode/postcode> ?pc.",
"  ?school <http://www.w3.org/2006/vcard/ns#hasEmail> ?email.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#lat> ?lat.",
"  ?pc <http://www.w3.org/2003/01/geo/wgs84_pos#long> ?long.",
"  OPTIONAL{",
"    ?school <http://www.w3.org/2000/01/rdf-schema#label> ?name",
"  }",
"  GRAPH <http://data.opendatascotland.org/graph/education/pupils-by-school-and-datazone>{",
"    ?x <http://data.opendatascotland.org/def/statistical-dimensions/education/school> ?school.",
"    ?x <http://data.opendatascotland.org/def/education/numberOfPupils> ?nop.",
"  }",
"  ?school <http://data.opendatascotland.org/def/education/department> ?dep.",
"  ?dep <http://data.opendatascotland.org/def/education/stageOfEducation> <http://data.opendatascotland.org/def/concept/education/stages-of-education/%{stage}>.",
"}",
"GROUP BY ?email ?lat ?long ?size ?name",
"ORDER BY ?email"]).join("\n");

var schools = {};

var DEBUG = true;

// schoolType one of "secondary", "primary", "pre-school"
//do not call directly, called from "redraw()"
function requestData(schoolType){
  var schoolsUrl = "http://data.opendatascotland.org/sparql.json?query=" +
    encodeURIComponent(schoolsSparql) + "&stage=" +
    encodeURIComponent(schoolType);
  $.ajax({
    dataType: 'text',
    url: schoolsUrl,
    success: function(data){
      data = JSON.parse(data).results.bindings;
      for(var i = 0; i < data.length - 1; i++){
        schools[data[i].email.value] = {
          'email': data[i].email.value,
          'name': data[i].name ? data[i].name.value : null,
          'latLong': new google.maps.LatLng(parseFloat(data[i].lat.value),
              parseFloat(data[i].long.value)),
          'size': parseInt(data[i].size.value),
          'conns': []
        };
      }
      requestConnData(schoolType, 1);
    }
  });
}

function requestConnData(schoolType, page){
  var connsUrl = "http://data.opendatascotland.org/sparql.json?query=" +
    encodeURIComponent(connsSparql) + "&stage=" +
    encodeURIComponent(schoolType) + "&per_page=10000&page=" + page;
  $.ajax({
    dataType: 'text',
    url: connsUrl,
    success: function(data){
      var found = false;
      data = JSON.parse(data).results.bindings;
      if(data.length != 0)
        found = true;
      for(var i = 0; i < data.length - 1; i++){
        if(!(data[i].email.value in schools))
          continue;
        schools[data[i].email.value].conns.push({
          'latLong': new google.maps.LatLng(parseFloat(data[i].lat.value),
              parseFloat(data[i].long.value)),
          'strength': parseInt(data[i].strength.value)
        });
      }
      if(found){
        requestConnData(schoolType, page + 1);
      }
      else{
        drawConns();
        drawSchools();
      }
    }
  });
}

//boolean values as objects so that they are mutable form inside the button listener
var showingPreSchools = {value: false};
var showingPrimarySchools = {value: false};
var showingSecondarySchools = {value: true};

//TODO make redraw hide and show objects rather than re-calling the database.
function redraw() {
  clean(); //remove everything

  if(DEBUG) {
	console.log("Showing Pre-Schools: " + showingPreSchools.value);
	console.log("Showing Primary Schools: " + showingPrimarySchools.value);
	console.log("Showing Secondary Schools: " + showingSecondarySchools.value);
  }

  if(showingPreSchools.value) { //if supposed to be drawing; draw.
    requestData("pre-school");
  }

  if(showingPrimarySchools.value) {
    requestData("primary");
  }

  if(showingSecondarySchools.value) {
    requestData("secondary");
  }
}

redraw();

//removed all currently drawing map objects.
function clean() {
  for(var key in schools){
    schools[key].ui.circle.setMap(null);
    schools[key].ui.infowindow.close();
    for(var j = 0; j < schools[key].conns.length; j++){
      var conn = schools[key].conns[j];
      if(conn.ui)
        schools[key].conns[j].ui.setMap(null);
    }
  }
  schools = [];
}

function drawSchools(data){
  for(var key in schools){
    drawSchool(schools[key]);
  }
}

function drawConns(data){
  for(var key in schools){
    for(var i = 0; i < schools[key].conns.length; i++){
      var conn = schools[key].conns[i];
      if(conn.strength < 10)
        continue;
      drawPath(schools[key], conn);
    }
  }
}

function drawZone(map, zoneLatLong){
  drawPoint //what this? //
}

function drawArrow(map, zoneLatLong, schoolLatLong) {}

var map;

var mapStyles = [ { "featureType": "poi", "stylers": [ { "weight": 1.9 }, { "visibility": "off" } ] },{ "featureType": "poi.school", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.man_made", "stylers": [ { "visibility": "on" } ] },{ "featureType": "landscape.natural", "stylers": [ { "visibility": "off" } ] } ] ;

function initialize() {
  var centerLatlng = new google.maps.LatLng(56.632064,-3.729858);
  var mapOptions = {
    zoom: 7,
	disableDefaultUI: true,
    center: centerLatlng ,
    mapTypeControlOptions: {
        mapTypeIds: [google.maps.MapTypeId.ROADMAP, 'map_style']
      }
  }

  var mapDiv = document.getElementById('map-canvas');
  map = new google.maps.Map(mapDiv, mapOptions);

  map.setOptions({styles : mapStyles})

  var defStyle = [{}]

  var styledMap = new google.maps.StyledMapType(defStyle, {name: "Default"});
  map.mapTypes.set('map_style', styledMap);
  map.setMapTypeId('map_style');

  button(" Pre-", showingPreSchools);
  button(" Primary ", showingPrimarySchools);
  button(" Secondary ", showingSecondarySchools);
}

function button(type, bool) {
  var homeControlDiv = document.createElement('div');
  var bc = new buttonControl(homeControlDiv, type, bool);
  map.controls[google.maps.ControlPosition.RIGHT_TOP].push(homeControlDiv);
}

function buttonControl(controlDiv, type, bool) {
  var startDrawing = "Show" + type + "Schools";
  var stopDrawing = "Hide" + type + "Schools";
  var info = "Toggle" + type + "Schools";
  var showColor = "green";
  var hideColor = "red";

  controlDiv.style.padding = '5px';

  var controlUI = document.createElement('div');
  controlUI.style.backgroundColor = bool.value ? hideColor : showColor;
  controlUI.style.width = '160px';
  controlUI.style.borderStyle = 'solid';
  controlUI.style.borderWidth = '2px';
  controlUI.style.cursor = 'pointer';
  controlUI.style.textAlign = 'center';
  controlUI.title = info;
  controlDiv.appendChild(controlUI);

  var controlText = document.createElement('div');
  controlText.style.fontFamily = 'Arial,sans-serif';
  controlText.style.fontSize = '12px';
  controlText.style.paddingLeft = '4px';
  controlText.style.paddingRight = '4px';
  controlText.innerHTML = bool.value ? stopDrawing : startDrawing;
  controlUI.appendChild(controlText);

  google.maps.event.addDomListener(controlUI, 'click', function() {
	bool.value = !bool.value; //toggle the drawing state

    if(bool.value) { //if drawing
	  controlText.innerHTML = stopDrawing; //set button text to "stop drawing"
      controlUI.style.backgroundColor = hideColor;
	} else {
	  controlText.innerHTML = startDrawing; // set button text to "draw"
	  controlUI.style.backgroundColor = showColor;
	}
	redraw(); //redraw all the schools
  });
}

function drawPath(LatSchool, LongSchool, LatDataZone, LongDataZone) {
  drawPath(map, new google.maps.LatLng(LatSchool, LongSchool),
			new google.maps.LatLng(LatDataZone, LongDataZone)
  );
}

function drawPath(school, conn) {
  var options = {
    path: [conn.latLong, school.latLong],
    strokeOpacity: Math.min(1.0, (Math.log(conn.strength) - 2) / 2),
    strokeWeight: 1.0,
    icons: [{
      offset: '100%'
    }],
    map: map
  };

  conn.ui = new google.maps.Polyline(options);
}

function drawSchool(school) {
  var options = {
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.25,
    map: map,
    center: school.latLong,
    radius: (school.size * 0.5)
  };

  var circ = new google.maps.Circle(options);
  school.ui = {
    'circle': circ,
    'infowindow': new google.maps.InfoWindow({
      content: '
' + school.name + '

' + "Students: " + school.size +  '
',
      position: circ.center
    })
  }

  google.maps.event.addListener(school.ui.circle, 'mouseover', function() {
    if (map.getZoom() > 8) {
      school.ui.infowindow.open(map) }
  });

  google.maps.event.addListener(school.ui.circle, 'mouseout', function() {
    school.ui.infowindow.close();
  });
}

//on load, run initialize
google.maps.event.addDomListener(window, 'load', initialize);

<|endoftext|>


<commit_before>///base on node built-in http module
const EventEmitter = require("events");
const util = require('util');
const request = require("request");
const config = require("./config.js").getAll();
const Readable = require('stream').Readable;
const http2 = require("http2");
const fs = require('fs');
const Dicer = require('dicer');
const BufferManager = require("./wakeup/buffermanager").BufferManager;

function DownStream() {
    EventEmitter.call(this);
    this.init();
}

//this.state: connecting/closed/connected

DownStream.prototype.isConnected = function() {
    return this.state == "connected";
};

DownStream.prototype.init = async function() {
    var self = this;
    if (this.state == "connecting") {
        return;
    }

    if (this.req) {
        try {
            this.req.rstWithCancel();
        } catch (e) {}
        this.req = null;
    }

    if (this.pingInterval) {
        clearInterval(this.pingInterval);
        if (this.pingReq) {
            try {
                this.pingReq.rstWithCancel();
            } catch (e) {}
            this.pingReq = null;
        }
    }

    if (this.http2session) {
        try {
            this.http2session.shutdown({
                graceful: true
            });
        } catch (e) {}
        this.http2session = null;
        await new Promise((resolve, reject) => {
            setTimeout(resolve, 1000);
        });
    }
    console.log(config.oauth_token);
    console.log("https://" + config.ip);
    this.http2session = http2.connect("https://" + config.ip,{rejectUnauthorized:false});
    this.http2session.socket.setNoDelay(true);

    this.http2session.on("error", () => {
        this.state = "closed";
        console.log('downstream session error!!!!!!!!');
    });
    this.http2session.on("close", () => {
        this.state = "closed";
        this.emit("sessionClosed");
        console.log('downstream session closed!!!!!!!!');
        //this.init();
    });
    var logid = config.device_id + "_" + new Date().getTime() + "_monitor";
    console.log("downstream logid:" + logid);
    this.req = this.http2session.request({
        ":path": config.directive_uri,
        "SAIYALOGID": logid,
        "authorization": "Bearer " + config.oauth_token,
        "Dueros-Device-Id": config.device_id
    });
    this.req.on("error", (e) => {
        console.log('downstream error!!!!!!!!' + e.toString());
    });
    this.req.on("streamClosed", () => {
        this.emit("streamClosed");
        console.log('downstream closed');
        this.init();
    });
    this.http2session.setTimeout(0, () => {
        console.log("downstream session timeout");
    });
    this.req.setTimeout(0, () => {
        console.log("downstream stream timeout");
    });
    this.state = "connecting";
    if (this.pingInterval) {
        clearInterval(this.pingInterval);
    }
    this.pingInterval = setInterval(() => {
        if (!this.http2session || this.http2session.aborted || this.http2session.destroyed) {
            console.log('downstream ping error, stream closed');
            if (this.pingInterval) {
                clearInterval(this.pingInterval);
            }
            return;
        }
        var req = this.pingReq = this.http2session.request({
            ":path": config.ping_uri,
            "authorization": "Bearer " + config.oauth_token,
            "Dueros-Device-Id": config.device_id
        });
        req.setTimeout(5000, () => {
            console.log("downstream ping timeout");
            if (!req.destroyed) {
                req.rstWithCancel();
            }
            if (this.req && !this.req.destroyed) {
                this.req.rstWithCancel();
            }
        });
        req.on("response", (headers) => {
            //console.log(headers[':status']);
            if (headers[':status'] != 200) {
                console.log("ping status error!!", headers);
                //this.init();
            }
        });
        setTimeout(() => {
            if (!req.destroyed) {
                req.rstWithCancel();
            }
        }, 5000);
        req.on("error", (e) => {
            console.log('downstream ping error!!!!!!!!' + e.toString());
            //this.init();
        });
    }, 5000);
    var d = this.dicer = new Dicer({
        "boundary": ""
    });
    d.on('error', () => {
        console.log('downstream dicer error, no multi part in downstream!!!!!!!!');
    });
    this.req.on('response', (headers) => {
        if (!this.req) {
            return;
        }
        this.state = "connected";
        console.log("downstream created!");
        this.emit("init");
        if (!headers['content-type']) {
            console.log(headers);
            throw new Error("server header error: no content-type");
        }
        var matches = headers['content-type'].match(/boundary=([^;]*)/);
        if (matches && matches[1]) {
            d.setBoundary(matches[1]);
        }
        this.req.on("data", (data) => {
            //console.log(data.toString());
        });
        let rWrap = new Readable().wrap(this.req);
        rWrap.pipe(fs.createWriteStream(__dirname + "/tmp/ds" + logid, {
            flags: 'w',
            defaultEncoding: 'binary',
            autoClose: true
        }));
        rWrap.pipe(d);
    });
    //content-type: multipart/form-data; boundary=___dumi_avs_xuejuntao___
    d.on('part', function(p) {
        //console.log("on part");
        var name = null;
        var jsonBody = new BufferManager();
        var response = null;
        p.on('header', function(header) {
            name = null;
            jsonBody.clear();
            response = null;
            //console.log(JSON.stringify(header, null, '  '));
            if (header["content-disposition"]) {
                var matches;
                if (matches = header["content-disposition"][0].match(/name="(\w+)"/)) {
                    name = matches[1];
                }
            }
            if (header['content-id']) {
                var content_id = header["content-id"][0].replace(/[<>]/g, "");
                //console.log("content_id:"+content_id);
                self.emit("content", content_id, p);
            }
        });
        p.on('data', function(data) {
            if (name == "metadata") {
                jsonBody.add(data);
            }
        });
        p.on('end', function() {
            if (jsonBody) {
                try {
                    response = JSON.parse(jsonBody.toBuffer().toString("utf8"));
                } catch (e) {}
                if (response) {
                    self.emit("directive", response);
                }
            }
            //console.log(JSON.stringify(response, null, '  '));
        });
        p.on('error', () => {
            console.log('downstream dicer error, event part error');
        });
    });
    d.on('finish', function() {
        //console.log('End of parts');
    });

}
util.inherits(DownStream, EventEmitter);

module.exports = DownStream;
<commit_msg>reconnect<commit_after>///base on node built-in http module
const EventEmitter = require("events");
const util = require('util');
const request = require("request");
const config = require("./config.js").getAll();
const Readable = require('stream').Readable;
const http2 = require("http2");
const fs = require('fs');
const Dicer = require('dicer');
const BufferManager = require("./wakeup/buffermanager").BufferManager;

function DownStream() {
    EventEmitter.call(this);
    this.init();
}

//this.state: connecting/closed/connected

DownStream.prototype.isConnected = function() {
    return this.state == "connected";
};

DownStream.prototype.init = async function() {
    var self = this;
    if (this.state == "connecting") {
        return;
    }

    if (this.req) {
        try {
            this.req.rstWithCancel();
        } catch (e) {}
        this.req = null;
    }

    if (this.pingInterval) {
        clearInterval(this.pingInterval);
        if (this.pingReq) {
            try {
                this.pingReq.rstWithCancel();
            } catch (e) {}
            this.pingReq = null;
        }
    }

    if (this.http2session) {
        try {
            this.http2session.shutdown({
                graceful: true
            });
        } catch (e) {}
        this.http2session = null;
        await new Promise((resolve, reject) => {
            setTimeout(resolve, 1000);
        });
    }
    console.log(config.oauth_token);
    console.log("https://" + config.ip);
    this.http2session = http2.connect("https://" + config.ip,{rejectUnauthorized:false});
    this.http2session.socket.setNoDelay(true);

    this.http2session.on("error", () => {
        this.state = "closed";
        console.log('downstream session error!!!!!!!!');
    });
    this.http2session.on("close", () => {
        this.state = "closed";
        this.emit("sessionClosed");
        console.log('downstream session closed!!!!!!!!');
        this.init();
    });
    var logid = config.device_id + "_" + new Date().getTime() + "_monitor";
    console.log("downstream logid:" + logid);
    this.req = this.http2session.request({
        ":path": config.directive_uri,
        "SAIYALOGID": logid,
        "authorization": "Bearer " + config.oauth_token,
        "Dueros-Device-Id": config.device_id
    });
    this.req.on("error", (e) => {
        console.log('downstream error!!!!!!!!' + e.toString());
    });
    this.req.on("streamClosed", () => {
        this.emit("streamClosed");
        console.log('downstream closed');
        this.init();
    });
    this.http2session.setTimeout(0, () => {
        console.log("downstream session timeout");
    });
    this.req.setTimeout(0, () => {
        console.log("downstream stream timeout");
    });
    this.state = "connecting";
    if (this.pingInterval) {
        clearInterval(this.pingInterval);
    }
    this.pingInterval = setInterval(() => {
        if (!this.http2session || this.http2session.aborted || this.http2session.destroyed) {
            console.log('downstream ping error, stream closed');
            if (this.pingInterval) {
                clearInterval(this.pingInterval);
            }
            return;
        }
        var req = this.pingReq = this.http2session.request({
            ":path": config.ping_uri,
            "authorization": "Bearer " + config.oauth_token,
            "Dueros-Device-Id": config.device_id
        });
        req.setTimeout(5000, () => {
            console.log("downstream ping timeout");
            if (!req.destroyed) {
                req.rstWithCancel();
            }
            if (this.req && !this.req.destroyed) {
                this.req.rstWithCancel();
            }
        });
        req.on("response", (headers) => {
            //console.log(headers[':status']);
            if (headers[':status'] != 200) {
                console.log("ping status error!!", headers);
                //this.init();
            }
        });
        setTimeout(() => {
            if (!req.destroyed) {
                req.rstWithCancel();
            }
        }, 5000);
        req.on("error", (e) => {
            console.log('downstream ping error!!!!!!!!' + e.toString());
            //this.init();
        });
    }, 5000);
    var d = this.dicer = new Dicer({
        "boundary": ""
    });
    d.on('error', () => {
        console.log('downstream dicer error, no multi part in downstream!!!!!!!!');
    });
    this.req.on('response', (headers) => {
        if (!this.req) {
            return;
        }
        this.state = "connected";
        console.log("downstream created!");
        this.emit("init");
        if (!headers['content-type']) {
            console.log(headers);
            throw new Error("server header error: no content-type");
        }
        var matches = headers['content-type'].match(/boundary=([^;]*)/);
        if (matches && matches[1]) {
            d.setBoundary(matches[1]);
        }
        this.req.on("data", (data) => {
            //console.log(data.toString());
        });
        let rWrap = new Readable().wrap(this.req);
        rWrap.pipe(fs.createWriteStream(__dirname + "/tmp/ds" + logid, {
            flags: 'w',
            defaultEncoding: 'binary',
            autoClose: true
        }));
        rWrap.pipe(d);
    });
    //content-type: multipart/form-data; boundary=___dumi_avs_xuejuntao___
    d.on('part', function(p) {
        //console.log("on part");
        var name = null;
        var jsonBody = new BufferManager();
        var response = null;
        p.on('header', function(header) {
            name = null;
            jsonBody.clear();
            response = null;
            //console.log(JSON.stringify(header, null, '  '));
            if (header["content-disposition"]) {
                var matches;
                if (matches = header["content-disposition"][0].match(/name="(\w+)"/)) {
                    name = matches[1];
                }
            }
            if (header['content-id']) {
                var content_id = header["content-id"][0].replace(/[<>]/g, "");
                //console.log("content_id:"+content_id);
                self.emit("content", content_id, p);
            }
        });
        p.on('data', function(data) {
            if (name == "metadata") {
                jsonBody.add(data);
            }
        });
        p.on('end', function() {
            if (jsonBody) {
                try {
                    response = JSON.parse(jsonBody.toBuffer().toString("utf8"));
                } catch (e) {}
                if (response) {
                    self.emit("directive", response);
                }
            }
            //console.log(JSON.stringify(response, null, '  '));
        });
        p.on('error', () => {
            console.log('downstream dicer error, event part error');
        });
    });
    d.on('finish', function() {
        //console.log('End of parts');
    });

}
util.inherits(DownStream, EventEmitter);

module.exports = DownStream;
<|endoftext|>