<commit_before>"use strict";
var Utils = {
  makeNullProto: function() {
    return {__proto__: null};
  },
  fetchHttpContents: function(url, success) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        success(this.responseText);
      }
    };
    req.send();
    return req;
  },
  _escapeRe: /[&<>]/g,
  _escapeCallback: function(c, n) {
    n = c.charCodeAt(0);
    return (n === 60) ? "<" : (n === 62) ? ">" : "&";
  },
  escapeHtml: function(s) {
    return s.replace(this._escapeRe, this._escapeCallback);
  },
  // "javascript" should be treated specially
  _nonUrlPrefixes: { about: 1, blob: 1, data: 1, mailto: 1, "view-source": 1 },
  _chromePrefixes: { "chrome-extension": 1, "chrome-search": 1 },
  _urlPrefix: /^[a-z]{3,}:\/\//,
  hasOrdinaryUrlPrefix: function(url) {
    return this._urlPrefix.test(url);
  },
  // url: only accept real tab's
  isRefusingIncognito: function(url) {
    url = url.toLowerCase();
    if (url.startsWith('chrome://')) {
      return !url.startsWith("chrome://downloads");
    }
    return !url.startsWith(Settings.CONST.ChromeInnerNewTab) && url.startsWith('chrome');
  },
  _hostRe: /^([^:]+(:[^:]+)?@)?([^:]+|\[[^\]]+\])(:\d+)?$/,
  _nonENTlds: ".\u4e2d\u56fd",
  _tlds: ["", "",
    ".ac.ad.ae.af.ag.ai.al.am.an.ao.aq.ar.as.at.au.aw.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.eh.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.su.sv.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.tt.tv.tw.tz.ua.ug.uk.um.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.yu.za.zm.zw",
    ".biz.cat.com.edu.gov.int.mil.mtn.net.org.pro.tel.top.xxx",
    ".aero.arpa.asia.club.coop.info.jobs.mobi.name.post",
    ".local",
    ".museum.travel"
  ],
  _ipRe: /^(\d{1,3}\.){3}\d{1,3}$/,
  spacesRe: /[\s\u3000]+/g,
  _nonENTldRe: /[^a-z]/,
  _jsNotEscapeRe: /["\[\]{}\u00ff-\uffff]|%(?![\dA-F]{2}|[\da-f]{2})/,
  filePathRe: /^['"]?((?:[A-Za-z]:[\\/]|\/(?:Users|home|root)\/)[^'"]*)['"]?$/,
  convertToUrl: function(string, keyword) {
    if (string.substring(0, 11).toLowerCase() === "javascript:") {
      if (Settings.CONST.ChromeVersion < 46 && string.indexOf('%', 11) > 0
          && !this._jsNotEscapeRe.test(string)) {
        string = this.decodeURLPart(string);
      }
      return string;
    }
    var type = -1, expected = 1, index, index2, oldString, arr;
    // NOTE: here '\u3000' is changed to ' ', which may cause a 404 (for url)
    // NOTE: here a mulit-line string is be changed to single-line,
    //       which may be better
    oldString = string.replace(this.spacesRe, ' ').trim();
    string = oldString.toLowerCase();
    if ((index = string.indexOf(' ')) > 0) {
      string = string.substring(0, index);
    }
    if ((index = string.indexOf(':')) === 0) { type = 2; }
    else if (index === -1 || string.substring(index, index + 3) !== "://") {
      if (index !== -1 && string.substring(0, index) in this._nonUrlPrefixes) {
        index2 = string.length;
        type = index2 < oldString.length || index2 <= index
          || string.charCodeAt(index + 1) === 47 ? 2 : 0;
      } else if (string.startsWith("//")) {
        string = string.substring(2);
        index2 = 2;
      } else {
        index2 = 0;
      }
      if (type !== -1) {}
      else if ((index = string.indexOf('/')) <= 0) {
        if (index === 0 || string.length < oldString.length - index2) { type = 2; }
      } else if (string.length >= oldString.length - index2 ||
          ((index2 = string.charCodeAt(index + 1)) > 32 && index2 !== 47)) {
        string = string.substring(0, index);
      } else {
        type = 2;
      }
    }
    else if (this._nonENTldRe.test(string.substring(0, index))) {
      type = (string.substring(0, index) in this._chromePrefixes)
        && (index = string.charCodeAt(index + 3)) > 32 && index !== 47 ? 0 : 2;
    }
    else if (string.startsWith("file:")) {
      if (string.charCodeAt(7) !== 47) {
        type = 2;
      } else {
        index = string.charCodeAt(8);
        type = (index > 32 && index !== 47) ? 0 : 2; // `>32`: in case of NaN
      }
    }
    else if (string.startsWith("chrome:")) {
      type = string.length < oldString.length && string.indexOf('/', 9) === -1
        ? 2 : 0;
    }
    else if (string.startsWith("vimium:")) {
      type = 0;
      oldString = chrome.runtime.getURL("/") + oldString.substring(9);
    }
    else if (index2 = string.indexOf('/', index += 3),
        string.length >= oldString.length) {
      string = string.substring(index, index2 !== -1 ? index2 : undefined);
      expected = 0;
    }
    else if (index2 <= index || (expected = string.charCodeAt(index2 + 1),
        !(expected > 32) || expected === 47 )) {
      type = 2;
    } else {
      string = string.substring(index, index2);
      expected = 0;
    }

    if (type !== -1) {
    } else if (!(arr = this._hostRe.exec(string))) {
      type = 2;
    } else if ((string = arr[3]).indexOf(':') !== -1
        || string.endsWith("localhost")) {
      type = expected;
    } else if ((index = string.lastIndexOf('.')) <= 0) {
      type = 2;
    } else if (this._ipRe.test(string)) {
      type = expected;
    } else if (!this.isTld(string.substring(index + 1))) {
      type = 2;
    } else if (expected === 0) {
      type = 0;
    } else if (arr[2] || arr[4] || !arr[1] || string.startsWith("ftp")) {
      type = 1;
    // the below means string is like "(?<=abc@)(uvw.)*xyz.tld"
    } else if (string.startsWith("mail") || string.indexOf(".mail") > 0
        || (index2 = string.indexOf(".")) === index) {
      type = 2;
    } else if (string.indexOf(".", ++index2) !== index) {
      type = 1;
    } else {
      type = this.isTld(string.substring(index2, index)) ? 2 : 1;
    }
    // window.type = type;
    return type === 0 ? oldString : type === 1
      ? ((oldString.startsWith("//") ? "http:" : "http://") + oldString)
      : this.createSearchUrl(oldString.split(' '), keyword || "~");
  },
  isTld: function(tld) {
    if (this._nonENTldRe.test(tld)) {
      return this._nonENTlds.indexOf(tld) !== -1;
    } else if (tld.length < this._tlds.length) {
      return this._tlds[tld.length].indexOf(tld) > 0;
    }
    return false;
  },
  searchWordRe: /%[sS]/g,
  createSearchUrl: function(query, keyword) {
    query = this.createSearch(query, Settings.get("searchEnginesMap")[keyword]).url;
    if (keyword != "~") {
      query = this.convertToUrl(query);
    }
    return query;
  },
  createSearch: function(query, pattern, $S) {
    var queryStr;
    if ($S != null ? ($S === true) : pattern.$S) {
      $S = query.join(' ');
    }
    if (pattern.$s) {
      queryStr = query.map(encodeURIComponent).join('+');
    }
    return {
      url: pattern.url.replace(this.searchWordRe, function(s) {
        return (s === "%s") ? queryStr : $S;
      }),
      $s: queryStr,
      $S: $S
    };
  },
  decodeURLPart: function(url) {
    try {
      url = decodeURIComponent(url);
    } catch (e) {}
    return url;
  },
  parseSearchEngines: function(searchEnginesText, map) {
    var a, pairs, key, val, name, obj, _i, _j, _len, _len2, key0, //
    rEscapeSpace = /\\\s/g, rSpace = /\s/, rEscapeS = /\\s/g, rColon = /\\:/g;
    a = searchEnginesText.replace(/\\\n/g, '').split('\n');
    for (_i = 0, _len = a.length; _i < _len; _i++) {
      val = a[_i].trim();
      if (!(val.charCodeAt(0) > 35)) { continue; } // mask: /[ !"#]/
      _j = 0;
      do {
        _j = val.indexOf(":", _j + 1);
      } while (val[_j - 1] === '\\');
      if (_j <= 0 || !(key = val.substring(0, _j).trimRight())) continue;
      val = val.substring(_j + 1).trimLeft();
      if (!val) continue;
      val = val.replace(rEscapeSpace, "\\s");
      _j = val.search(rSpace);
      if (_j > 0) {
        name = val.substring(_j + 1).trimLeft();
        key0 = "";
        val = val.substring(0, _j);
      } else {
        name = null;
      }
      val = val.replace(rEscapeS, " ");
      obj = {url: val};
      key = key.replace(rColon, ":");
      pairs = key.split('|');
      for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
        if (key = pairs[_j].trim()) {
          if (name) {
            if (!key0) { key0 = key; }
          } else {
            key0 = name = key;
          }
          map[key] = obj;
        }
      }
      if (!name) continue;
      obj.name = name;
      obj.$s = val.indexOf("%s") + 1;
      obj.$S = val.indexOf("%S") + 1;
      if (pairs = this.reparseSearchUrl(obj, key0)) {
        map[""].push(pairs);
      }
    }
  },
  reparseSearchUrl: function (pattern, name) {
    var url, ind = pattern.$s || pattern.$S, prefix;
    if (!ind) { return; }
    url = pattern.url.toLowerCase();
    if (!(this.hasOrdinaryUrlPrefix(url) || url.startsWith("chrome-"))) { return; }
    url = url.substring(0, ind - 1);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      prefix = url.substring(0, ind - 1);
      url = url.substring(ind);
      if (ind = url.lastIndexOf("&") + 1) {
        url = url.substring(ind);
      }
      if (url && url !== "=" && !url.endsWith("/")) {
        return this.makeReparser(prefix, "[?#&]", url, "([^&#]*)", name)
      }
      url = pattern.url.substring(0, (pattern.$s || pattern.$S) - 1);
    }
    prefix = url;
    url = pattern.url.substring(url.length + 2);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      url = url.substring(0, ind);
    }
    return this.makeReparser(prefix, "^([^?#]*)", url, "", name);
  },
  escapeAllRe: /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  makeReparser: function(head, prefix, url, suffix, name) {
    url = url.toLowerCase().replace(this.escapeAllRe, "\\$&");
    if (head.startsWith("https://")) {
      head = "http" + head.substring(5);
    } else if (head.toLowerCase().startsWith("vimium://")) {
      head = chrome.runtime.getURL("/") + head.substring(9);
    }
    return [head, new RegExp(prefix + url + suffix, "i"), name];
  },
  Decoder: null,
  upperRe: /[A-Z]/
};

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(s) {
  return this.length >= s.length && this.lastIndexOf(s, 0) === 0;
};
String.prototype.endsWith || (String.prototype.endsWith = function(s) {
  var i = this.length - s.length;
  return i >= 0 && this.indexOf(s, i) === i;
});
}
<commit_msg>small changes<commit_after>"use strict";
var Utils = {
  makeNullProto: function() {
    return {__proto__: null};
  },
  fetchHttpContents: function(url, success) {
    var req = new XMLHttpRequest();
    req.open("GET", url, true);
    req.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        success(this.responseText);
      }
    };
    req.send();
    return req;
  },
  _escapeRe: /[&<>]/g,
  _escapeCallback: function(c, n) {
    n = c.charCodeAt(0);
    return (n === 60) ? "<" : (n === 62) ? ">" : "&";
  },
  escapeHtml: function(s) {
    return s.replace(this._escapeRe, this._escapeCallback);
  },
  // "javascript" should be treated specially
  _nonUrlPrefixes: { about: 1, blob: 1, data: 1, mailto: 1, "view-source": 1 },
  _chromePrefixes: { "chrome-extension": 1, "chrome-search": 1 },
  _urlPrefix: /^[a-z]{3,}:\/\//,
  hasOrdinaryUrlPrefix: function(url) {
    return this._urlPrefix.test(url);
  },
  // url: only accept real tab's
  isRefusingIncognito: function(url) {
    url = url.toLowerCase();
    if (url.startsWith('chrome://')) {
      return !url.startsWith("chrome://downloads");
    }
    return !url.startsWith(Settings.CONST.ChromeInnerNewTab) && url.startsWith('chrome');
  },
  _nonENTlds: ".\u4e2d\u56fd",
  _tlds: ["", "",
    ".ac.ad.ae.af.ag.ai.al.am.an.ao.aq.ar.as.at.au.aw.az.ba.bb.bd.be.bf.bg.bh.bi.bj.bm.bn.bo.br.bs.bt.bv.bw.by.bz.ca.cc.cd.cf.cg.ch.ci.ck.cl.cm.cn.co.cr.cu.cv.cx.cy.cz.de.dj.dk.dm.do.dz.ec.ee.eg.eh.er.es.et.eu.fi.fj.fk.fm.fo.fr.ga.gd.ge.gf.gg.gh.gi.gl.gm.gn.gp.gq.gr.gs.gt.gu.gw.gy.hk.hm.hn.hr.ht.hu.id.ie.il.im.in.io.iq.ir.is.it.je.jm.jo.jp.ke.kg.kh.ki.km.kn.kp.kr.kw.ky.kz.la.lb.lc.li.lk.lr.ls.lt.lu.lv.ly.ma.mc.md.me.mg.mh.mk.ml.mm.mn.mo.mp.mq.mr.ms.mt.mu.mv.mw.mx.my.mz.na.nc.ne.nf.ng.ni.nl.no.np.nr.nu.nz.om.pa.pe.pf.pg.ph.pk.pl.pm.pn.pr.ps.pt.pw.py.qa.re.ro.ru.rw.sa.sb.sc.sd.se.sg.sh.si.sj.sk.sl.sm.sn.so.sr.ss.st.su.sv.sy.sz.tc.td.tf.tg.th.tj.tk.tl.tm.tn.to.tp.tr.tt.tv.tw.tz.ua.ug.uk.um.us.uy.uz.va.vc.ve.vg.vi.vn.vu.wf.ws.ye.yt.yu.za.zm.zw",
    ".biz.cat.com.edu.gov.int.mil.mtn.net.org.pro.tel.top.xxx",
    ".aero.arpa.asia.club.coop.info.jobs.mobi.name.post",
    ".local",
    ".museum.travel"
  ],
  _hostRe: /^([^:]+(:[^:]+)?@)?([^:]+|\[[^\]]+\])(:\d{2,5})?$/,
  _ipRe: /^(\d{1,3}\.){3}\d{1,3}$/,
  spacesRe: /[\s\u3000]+/g,
  _nonENTldRe: /[^a-z]/,
  _jsNotEscapeRe: /["\[\]{}\u00ff-\uffff]|%(?![\dA-F]{2}|[\da-f]{2})/,
  filePathRe: /^['"]?((?:[A-Za-z]:[\\/]|\/(?:Users|home|root)\/)[^'"]*)['"]?$/,
  convertToUrl: function(string, keyword) {
    if (string.substring(0, 11).toLowerCase() === "javascript:") {
      if (Settings.CONST.ChromeVersion < 46 && string.indexOf('%', 11) > 0
          && !this._jsNotEscapeRe.test(string)) {
        string = this.decodeURLPart(string);
      }
      return string;
    }
    var type = -1, expected = 1, index, index2, oldString, arr;
    // NOTE: here '\u3000' is changed to ' ', which may cause a 404 (for url)
    // NOTE: here a mulit-line string is be changed to single-line,
    //       which may be better
    oldString = string.replace(this.spacesRe, ' ').trim();
    string = oldString.toLowerCase();
    if ((index = string.indexOf(' ')) > 0) {
      string = string.substring(0, index);
    }
    if ((index = string.indexOf(':')) === 0) { type = 2; }
    else if (index === -1 || string.substring(index, index + 3) !== "://") {
      if (index !== -1 && string.substring(0, index) in this._nonUrlPrefixes) {
        index2 = string.length;
        type = index2 < oldString.length || index2 <= index
          || string.charCodeAt(index + 1) === 47 ? 2 : 0;
      } else if (string.startsWith("//")) {
        string = string.substring(2);
        index2 = 2;
      } else {
        index2 = 0;
      }
      if (type !== -1) {}
      else if ((index = string.indexOf('/')) <= 0) {
        if (index === 0 || string.length < oldString.length - index2) { type = 2; }
      } else if (string.length >= oldString.length - index2 ||
          ((index2 = string.charCodeAt(index + 1)) > 32 && index2 !== 47)) {
        string = string.substring(0, index);
      } else {
        type = 2;
      }
    }
    else if (this._nonENTldRe.test(string.substring(0, index))) {
      type = (string.substring(0, index) in this._chromePrefixes)
        && (index = string.charCodeAt(index + 3)) > 32 && index !== 47 ? 0 : 2;
    }
    else if (string.startsWith("file:")) {
      if (string.charCodeAt(7) !== 47) {
        type = 2;
      } else {
        index = string.charCodeAt(8);
        type = (index > 32 && index !== 47) ? 0 : 2; // `>32`: in case of NaN
      }
    }
    else if (string.startsWith("chrome:")) {
      type = string.length < oldString.length && string.indexOf('/', 9) === -1 ? 2 : 0;
    }
    else if (string.startsWith("vimium:")) {
      type = 0;
      oldString = chrome.runtime.getURL("/") + oldString.substring(9);
    }
    else if (index2 = string.indexOf('/', index += 3),
        string.length >= oldString.length) {
      string = string.substring(index, index2 !== -1 ? index2 : undefined);
      expected = 0;
    }
    else if (index2 <= index || (expected = string.charCodeAt(index2 + 1),
        !(expected > 32) || expected === 47 )) {
      type = 2;
    } else {
      string = string.substring(index, index2);
      expected = 0;
    }

    if (type !== -1) {
    } else if (!(arr = this._hostRe.exec(string))) {
      type = 2;
    } else if ((string = arr[3]).indexOf(':') !== -1
        || string.endsWith("localhost")) {
      type = expected;
    } else if ((index = string.lastIndexOf('.')) <= 0) {
      type = 2;
    } else if (this._ipRe.test(string)) {
      type = expected;
    } else if (!this.isTld(string.substring(index + 1))) {
      type = 2;
    } else if (expected === 0) {
      type = 0;
    } else if (arr[2] || arr[4] || !arr[1] || string.startsWith("ftp")) {
      type = 1;
    // the below means string is like "(?<=abc@)(uvw.)*xyz.tld"
    } else if (string.startsWith("mail") || string.indexOf(".mail") > 0
        || (index2 = string.indexOf(".")) === index) {
      type = 2;
    } else if (string.indexOf(".", ++index2) !== index) {
      type = 1;
    } else {
      type = this.isTld(string.substring(index2, index)) ? 2 : 1;
    }
    // window.type = type;
    return type === 0 ? oldString : type === 1
      ? ((oldString.startsWith("//") ? "http:" : "http://") + oldString)
      : this.createSearchUrl(oldString.split(' '), keyword || "~");
  },
  isTld: function(tld) {
    if (this._nonENTldRe.test(tld)) {
      return this._nonENTlds.indexOf(tld) !== -1;
    } else if (tld.length < this._tlds.length) {
      return this._tlds[tld.length].indexOf(tld) > 0;
    }
    return false;
  },
  searchWordRe: /%[sS]/g,
  createSearchUrl: function(query, keyword) {
    query = this.createSearch(query, Settings.get("searchEnginesMap")[keyword]).url;
    if (keyword != "~") {
      query = this.convertToUrl(query);
    }
    return query;
  },
  createSearch: function(query, pattern, $S) {
    var queryStr;
    if ($S != null ? ($S === true) : pattern.$S) {
      $S = query.join(' ');
    }
    if (pattern.$s) {
      queryStr = query.map(encodeURIComponent).join('+');
    }
    return {
      url: pattern.url.replace(this.searchWordRe, function(s) {
        return (s === "%s") ? queryStr : $S;
      }),
      $s: queryStr,
      $S: $S
    };
  },
  decodeURLPart: function(url) {
    try {
      url = decodeURIComponent(url);
    } catch (e) {}
    return url;
  },
  parseSearchEngines: function(searchEnginesText, map) {
    var a, pairs, key, val, name, obj, _i, _j, _len, _len2, key0, //
    rEscapeSpace = /\\\s/g, rSpace = /\s/, rEscapeS = /\\s/g, rColon = /\\:/g;
    a = searchEnginesText.replace(/\\\n/g, '').split('\n');
    for (_i = 0, _len = a.length; _i < _len; _i++) {
      val = a[_i].trim();
      if (!(val.charCodeAt(0) > 35)) { continue; } // mask: /[ !"#]/
      _j = 0;
      do {
        _j = val.indexOf(":", _j + 1);
      } while (val[_j - 1] === '\\');
      if (_j <= 0 || !(key = val.substring(0, _j).trimRight())) continue;
      val = val.substring(_j + 1).trimLeft();
      if (!val) continue;
      val = val.replace(rEscapeSpace, "\\s");
      _j = val.search(rSpace);
      if (_j > 0) {
        name = val.substring(_j + 1).trimLeft();
        key0 = "";
        val = val.substring(0, _j);
      } else {
        name = null;
      }
      val = val.replace(rEscapeS, " ");
      obj = {url: val};
      key = key.replace(rColon, ":");
      pairs = key.split('|');
      for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
        if (key = pairs[_j].trim()) {
          if (name) {
            if (!key0) { key0 = key; }
          } else {
            key0 = name = key;
          }
          map[key] = obj;
        }
      }
      if (!name) continue;
      obj.name = name;
      obj.$s = val.indexOf("%s") + 1;
      obj.$S = val.indexOf("%S") + 1;
      if (pairs = this.reparseSearchUrl(obj, key0)) {
        map[""].push(pairs);
      }
    }
  },
  reparseSearchUrl: function (pattern, name) {
    var url, ind = pattern.$s || pattern.$S, prefix;
    if (!ind) { return; }
    url = pattern.url.toLowerCase();
    if (!(this.hasOrdinaryUrlPrefix(url) || url.startsWith("chrome-"))) { return; }
    url = url.substring(0, ind - 1);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      prefix = url.substring(0, ind - 1);
      url = url.substring(ind);
      if (ind = url.lastIndexOf("&") + 1) {
        url = url.substring(ind);
      }
      if (url && url !== "=" && !url.endsWith("/")) {
        return this.makeReparser(prefix, "[?#&]", url, "([^&#]*)", name)
      }
      url = pattern.url.substring(0, (pattern.$s || pattern.$S) - 1);
    }
    prefix = url;
    url = pattern.url.substring(url.length + 2);
    if (ind = (url.indexOf("?") + 1) || (url.indexOf("#") + 1)) {
      url = url.substring(0, ind);
    }
    return this.makeReparser(prefix, "^([^?#]*)", url, "", name);
  },
  escapeAllRe: /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
  makeReparser: function(head, prefix, url, suffix, name) {
    url = url.toLowerCase().replace(this.escapeAllRe, "\\$&");
    if (head.startsWith("https://")) {
      head = "http" + head.substring(5);
    } else if (head.toLowerCase().startsWith("vimium://")) {
      head = chrome.runtime.getURL("/") + head.substring(9);
    }
    return [head, new RegExp(prefix + url + suffix, "i"), name];
  },
  Decoder: null,
  upperRe: /[A-Z]/
};

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(s) {
  return this.length >= s.length && this.lastIndexOf(s, 0) === 0;
};
String.prototype.endsWith || (String.prototype.endsWith = function(s) {
  var i = this.length - s.length;
  return i >= 0 && this.indexOf(s, i) === i;
});
}
<|endoftext|>


<commit_before>describe("Modifiers", function() {

  var ___ = 0;

  it('regular expressions don\'t have to be case-sensitive', function() {
    // In many programming languages, especially those that
    // use the /^whatever$/ pattern syntax, modifiers are single
    // characters that come after the //.
    //
    // To make a JavaScript Pattern non-case-sensitive,
    // put "i" after the //.
    //
    // Note: Some programming languages do not support modifiers like
    // this. These languages typically have a flag that can be set
    // within the pattern string to toggle case-sensitivity. Refer
    // to the language API to see how to make a case-insensitive match
    // in your language.

    var fixThisPattern = /^abc$/;

    expect( 'abc' ).toMatch(fixThisPattern);
    expect( 'ABC' ).toMatch(fixThisPattern);
    expect( 'AbC' ).toMatch(fixThisPattern);

    expect(fixThisPattern.source).not.toMatch(/\[/);
  });

  it('match first or match all', function() {
    // //g -> match globally
    // By default, javascript // will match only the
    // first occurrence in the string which satisfies
    // the pattern. //g is useful especially when doing
    // find/replace in the string. We'll cover that in
    // a later Koan.
    //
    // The JavaScript String.match function returns
    // an array of matches.

    var singleMatch = /x/;
    var globalMatch = /x/g;

    expect( "xxx".match(singleMatch).length ).toEqual(___);
    expect( "xxx".match(globalMatch).length ).toEqual(___);
  });

  it('treat string as multiple lines', function() {
    // //m -> input string is multiple lines, so
    // ^ and $ match begin-end of each line, separated
    // by line feed. ^ and $ match intermediate
    // "lines" within input string

    // Hint: Notice "abc" appears twice in the matching string.

    var fixThisPattern = /^abc$/;

    var matches = "abc\nabc".match(fixThisPattern);

    expect( 'abc\nabc' ).toMatch(fixThisPattern);

    expect( matches.length ).toEqual(2);
    expect( matches[0]     ).toEqual("___");
    expect( matches[1]     ).toEqual("___");

    expect(fixThisPattern.source).not.toMatch(/n/);
  });

});
<commit_msg>Modifiers pass<commit_after>describe("Modifiers", function() {

  var ___ = 0;

  it('regular expressions don\'t have to be case-sensitive', function() {
    // In many programming languages, especially those that
    // use the /^whatever$/ pattern syntax, modifiers are single
    // characters that come after the //.
    //
    // To make a JavaScript Pattern non-case-sensitive,
    // put "i" after the //.
    //
    // Note: Some programming languages do not support modifiers like
    // this. These languages typically have a flag that can be set
    // within the pattern string to toggle case-sensitivity. Refer
    // to the language API to see how to make a case-insensitive match
    // in your language.

    var fixThisPattern = /^abc$/i;

    expect( 'abc' ).toMatch(fixThisPattern);
    expect( 'ABC' ).toMatch(fixThisPattern);
    expect( 'AbC' ).toMatch(fixThisPattern);

    expect(fixThisPattern.source).not.toMatch(/\[/);
  });

  it('match first or match all', function() {
    // //g -> match globally
    // By default, javascript // will match only the
    // first occurrence in the string which satisfies
    // the pattern. //g is useful especially when doing
    // find/replace in the string. We'll cover that in
    // a later Koan.
    //
    // The JavaScript String.match function returns
    // an array of matches.

    var singleMatch = /x/;
    var globalMatch = /x/g;

    expect( "xxx".match(singleMatch).length ).toEqual(1);
    expect( "xxx".match(globalMatch).length ).toEqual(3);
  });

  it('treat string as multiple lines', function() {
    // //m -> input string is multiple lines, so
    // ^ and $ match begin-end of each line, separated
    // by line feed. ^ and $ match intermediate
    // "lines" within input string

    // Hint: Notice "abc" appears twice in the matching string.

    var fixThisPattern = /^abc$/mg;

    var matches = "abc\nabc".match(fixThisPattern);

    expect( 'abc\nabc' ).toMatch(fixThisPattern);

    expect( matches.length ).toEqual(2);
    expect( matches[0]     ).toEqual("abc");
    expect( matches[1]     ).toEqual("abc");

    expect(fixThisPattern.source).not.toMatch(/n/);
  });

});
<|endoftext|>


<commit_before>/**
 * Generates the data received from Mocha's runner under a
 * standard format for the html report
 *
 * @param {Mocha.runner} runner - Mocha's runner
 * @param {generateCb} done
 */
module.exports = function(runner, done) {
  var indentLevel = -1,
      suites = [];

  runner.on('suite', function(suite) {
    suites.push({
      title: suite.title,
      indent: ++indentLevel,
      tests: []
    });
  });

  runner.on('test end', function(test) {
    suites[suites.length - 1].tests.push({
      title: test.title,
      status: test.state === 'passed' ? true : false,
      error: test.err,
      result: test.ctx.result
    });
  });

  runner.on('suite end', function(suite) {
    indentLevel--;
  });

  runner.on('end', function() {
    done(suites);
  });
}

/**
 * The test representing Mocha's "it"
 *
 * @typedef {Object} Test
 * @property {String} title - The description of the test
 * @property {Boolean} status - True => pass and false => fail
 * @property {Object} error - The error in case the test has failed
 * @property {Object} result - The result returned by
 *    [Mugshot]{@link https://github.com/uberVU/mugshot}
 */

/**
 * The suite representing the Mocha's "describe"
 *
 * @typedef {Object} Suite
 * @property {String} title - The description of the suite
 * @property {Array.<Test>} tests - An array with the tests of the suite
 */

/**
 * @callback generateCb
 * @param {Array.<Suite>} suites - The suites from the test files
 */
<commit_msg>remove inutile ternary operator<commit_after>/**
 * Generates the data received from Mocha's runner under a
 * standard format for the html report
 *
 * @param {Mocha.runner} runner - Mocha's runner
 * @param {generateCb} done
 */
module.exports = function(runner, done) {
  var indentLevel = -1,
      suites = [];

  runner.on('suite', function(suite) {
    suites.push({
      title: suite.title,
      indent: ++indentLevel,
      tests: []
    });
  });

  runner.on('test end', function(test) {
    suites[suites.length - 1].tests.push({
      title: test.title,
      status: test.state === 'passed',
      error: test.err,
      result: test.ctx.result
    });
  });

  runner.on('suite end', function(suite) {
    indentLevel--;
  });

  runner.on('end', function() {
    done(suites);
  });
}

/**
 * The test representing Mocha's "it"
 *
 * @typedef {Object} Test
 * @property {String} title - The description of the test
 * @property {Boolean} status - True => pass and false => fail
 * @property {Object} error - The error in case the test has failed
 * @property {Object} result - The result returned by
 *    [Mugshot]{@link https://github.com/uberVU/mugshot}
 */

/**
 * The suite representing the Mocha's "describe"
 *
 * @typedef {Object} Suite
 * @property {String} title - The description of the suite
 * @property {Array.<Test>} tests - An array with the tests of the suite
 */

/**
 * @callback generateCb
 * @param {Array.<Suite>} suites - The suites from the test files
 */
<|endoftext|>


<commit_before>//Dont change it
requirejs(['ext_editor_1', 'jquery_190', 'raphael_210', 'snap.svg_030'],
    function (ext, $, Raphael, Snap) {

        var cur_slide = {};

        ext.set_start_game(function (this_e) {
        });

        ext.set_process_in(function (this_e, data) {
            cur_slide = {};
            cur_slide["in"] = data[0];
            this_e.addAnimationSlide(cur_slide);
        });

        ext.set_process_out(function (this_e, data) {
            cur_slide["out"] = data[0];
        });

        ext.set_process_ext(function (this_e, data) {
            cur_slide.ext = data;
        });

        ext.set_process_err(function (this_e, data) {
            cur_slide['error'] = data[0];
            this_e.addAnimationSlide(cur_slide);
            cur_slide = {};
        });

        ext.set_animate_success_slide(function (this_e, options) {
            var $h = $(this_e.setHtmlSlide('

'));
            this_e.setAnimationHeight(115);
        });

        ext.set_animate_slide(function (this_e, data, options) {
            var $content = $(this_e.setHtmlSlide(ext.get_template('animation'))).find('.animation-content');
            if (!data) {
                console.log("data is undefined");
                return false;
            }

            //YOUR FUNCTION NAME
            var fname = 'distance';

            var checkioInput = data.in || ["51°28′48″N 0°0′0″E", "46°12′0″N, 6°9′0″E"];
            var checkioInputStr = fname + '(' + JSON.stringify(checkioInput[0]) + "," + JSON.stringify(checkioInput[1]) + ')';

            var failError = function (dError) {
                $content.find('.call').html(checkioInputStr);
                $content.find('.output').html(dError.replace(/\n/g, ","));

                $content.find('.output').addClass('error');
                $content.find('.call').addClass('error');
                $content.find('.answer').remove();
                $content.find('.explanation').remove();
                this_e.setAnimationHeight($content.height() + 60);
            };

            if (data.error) {
                failError(data.error);
                return false;
            }

            if (data.ext && data.ext.inspector_fail) {
                failError(data.ext.inspector_result_addon);
                return false;
            }

            $content.find('.call').html(checkioInputStr);
            $content.find('.output').html('Working...');

            if (data.ext) {
                var rightResult = data.ext["answer"];
                var userResult = data.out;
                var result = data.ext["result"];
                var result_addon = data.ext["result_addon"];

                //if you need additional info from tests (if exists)
                var explanation = data.ext["explanation"];
                $content.find('.output').html(' Your result: ' + JSON.stringify(userResult));
                if (!result) {
                    $content.find('.answer').html('Right result: ' + JSON.stringify(Math.round(rightResult * 10) / 10));
                    $content.find('.answer').addClass('error');
                    $content.find('.output').addClass('error');
                    $content.find('.call').addClass('error');
                }
                else {
                    $content.find('.answer').remove();
                }
            }
            else {
                $content.find('.answer').remove();
            }

            //Your code here about test explanation animation
            //$content.find(".explanation").html("Something text for example");
            //
            //
            //
            //
            //

            this_e.setAnimationHeight($content.height() + 60);

        });

        //This is for Tryit (but not necessary)
//        var $tryit;
//        ext.set_console_process_ret(function (this_e, ret) {
//            $tryit.find(".checkio-result").html("Result
" + ret);
//        });
//
//        ext.set_generate_animation_panel(function (this_e) {
//            $tryit = $(this_e.setHtmlTryIt(ext.get_template('tryit'))).find('.tryit-content');
//            $tryit.find('.bn-check').click(function (e) {
//                e.preventDefault();
//                this_e.sendToConsoleCheckiO("something");
//            });
//        });

        var colorOrange4 = "#F0801A";
        var colorOrange3 = "#FA8F00";
        var colorOrange2 = "#FAA600";
        var colorOrange1 = "#FABA00";

        var colorBlue4 = "#294270";
        var colorBlue3 = "#006CA9";
        var colorBlue2 = "#65A1CF";
        var colorBlue1 = "#8FC7ED";

        var colorGrey4 = "#737370";
        var colorGrey3 = "#9D9E9E";
        var colorGrey2 = "#C5C6C6";
        var colorGrey1 = "#EBEDED";

        var colorWhite = "#FFFFFF";
        //Your Additional functions or objects inside scope
        //
        //
        //

    }
);
<commit_msg>update js representation<commit_after>//Dont change it
requirejs(['ext_editor_1', 'jquery_190', 'raphael_210', 'snap.svg_030'],
    function (ext, $, Raphael, Snap) {

        var cur_slide = {};

        ext.set_start_game(function (this_e) {
        });

        ext.set_process_in(function (this_e, data) {
            cur_slide = {};
            cur_slide["in"] = data[0];
            this_e.addAnimationSlide(cur_slide);
        });

        ext.set_process_out(function (this_e, data) {
            cur_slide["out"] = data[0];
        });

        ext.set_process_ext(function (this_e, data) {
            cur_slide.ext = data;
        });

        ext.set_process_err(function (this_e, data) {
            cur_slide['error'] = data[0];
            this_e.addAnimationSlide(cur_slide);
            cur_slide = {};
        });

        ext.set_animate_success_slide(function (this_e, options) {
            var $h = $(this_e.setHtmlSlide('

'));
            this_e.setAnimationHeight(115);
        });

        ext.set_animate_slide(function (this_e, data, options) {
            var $content = $(this_e.setHtmlSlide(ext.get_template('animation'))).find('.animation-content');
            if (!data) {
                console.log("data is undefined");
                return false;
            }

            //YOUR FUNCTION NAME
            var fname = 'distance';

            var checkioInput = data.in || ["51°28′48″N 0°0′0″E", "46°12′0″N, 6°9′0″E"];
            var checkioInputStr = fname + '(u' + JSON.stringify(checkioInput[0]) + ", u" + JSON.stringify(checkioInput[1]) + ')';

            var failError = function (dError) {
                $content.find('.call').html(checkioInputStr);
                $content.find('.output').html(dError.replace(/\n/g, ","));

                $content.find('.output').addClass('error');
                $content.find('.call').addClass('error');
                $content.find('.answer').remove();
                $content.find('.explanation').remove();
                this_e.setAnimationHeight($content.height() + 60);
            };

            if (data.error) {
                failError(data.error);
                return false;
            }

            if (data.ext && data.ext.inspector_fail) {
                failError(data.ext.inspector_result_addon);
                return false;
            }

            $content.find('.call').html(checkioInputStr);
            $content.find('.output').html('Working...');

            if (data.ext) {
                var rightResult = data.ext["answer"];
                var userResult = data.out;
                var result = data.ext["result"];
                var result_addon = data.ext["result_addon"];

                //if you need additional info from tests (if exists)
                var explanation = data.ext["explanation"];
                $content.find('.output').html(' Your result: ' + JSON.stringify(userResult));
                if (!result) {
                    $content.find('.answer').html('Right result: ' + JSON.stringify(Math.round(rightResult * 10) / 10));
                    $content.find('.answer').addClass('error');
                    $content.find('.output').addClass('error');
                    $content.find('.call').addClass('error');
                }
                else {
                    $content.find('.answer').remove();
                }
            }
            else {
                $content.find('.answer').remove();
            }

            //Your code here about test explanation animation
            //$content.find(".explanation").html("Something text for example");
            //
            //
            //
            //
            //

            this_e.setAnimationHeight($content.height() + 60);

        });

        //This is for Tryit (but not necessary)
//        var $tryit;
//        ext.set_console_process_ret(function (this_e, ret) {
//            $tryit.find(".checkio-result").html("Result
" + ret);
//        });
//
//        ext.set_generate_animation_panel(function (this_e) {
//            $tryit = $(this_e.setHtmlTryIt(ext.get_template('tryit'))).find('.tryit-content');
//            $tryit.find('.bn-check').click(function (e) {
//                e.preventDefault();
//                this_e.sendToConsoleCheckiO("something");
//            });
//        });

        var colorOrange4 = "#F0801A";
        var colorOrange3 = "#FA8F00";
        var colorOrange2 = "#FAA600";
        var colorOrange1 = "#FABA00";

        var colorBlue4 = "#294270";
        var colorBlue3 = "#006CA9";
        var colorBlue2 = "#65A1CF";
        var colorBlue1 = "#8FC7ED";

        var colorGrey4 = "#737370";
        var colorGrey3 = "#9D9E9E";
        var colorGrey2 = "#C5C6C6";
        var colorGrey1 = "#EBEDED";

        var colorWhite = "#FFFFFF";
        //Your Additional functions or objects inside scope
        //
        //
        //

    }
);
<|endoftext|>


<commit_before>svgEditor.readLang({
	lang: "de",
	dir : "ltr",
	common: {
		"ok": "OK",
		"cancel": "Abbrechen",
		"key_backspace": "Rücktaste",
		"key_del": "Löschen",
		"key_down": "nach unten",
		"key_up": "nach oben",
		"more_opts": "More Options",
		"url": "URL",
		"width": "Width",
		"height": "Height"
	},
	misc: {
		"powered_by": "angetrieben durch"
	},
	ui: {
		"toggle_stroke_tools": "Zeige/Verberge weitere Linien Werkzeuge",
		"palette_info": "Klick zum Ändern der Füllfarbe, Shift-Klick zum Ändern der Linienfarbe",
		"zoom_level": "vergrößern",
		"panel_drag": "Drag left/right to resize side panel"
	},
	properties: {
		"id": "Identify the element",
		"fill_color": "Füllfarbe ändern",
		"stroke_color": "Linienfarbe ändern",
		"stroke_style": "Linienstil ändern",
		"stroke_width": "Linienbreite ändern",
		"pos_x": "Ändere die X Koordinate",
		"pos_y": "Ändere die Y Koordinate",
		"linecap_butt": "Form der Linienendung: Stumpf",
		"linecap_round": "Form der Linienendung: Rund",
		"linecap_square": "Form der Linienendung: Rechteckig",
		"linejoin_bevel": "Zusammentreffen von zwei Linien: abgeschrägte Kante",
		"linejoin_miter": "Zusammentreffen von zwei Linien: Gehrung",
		"linejoin_round": "Zusammentreffen von zwei Linien: Rund",
		"angle": "Drehwinkel ändern",
		"blur": "Ändere Gaußschen Weichzeichner Wert",
		"opacity": "Opazität des ausgewählten Objekts ändern",
		"circle_cx": "Kreiszentrum (cx) ändern",
		"circle_cy": "Kreiszentrum (cy) ändern",
		"circle_r": "Kreisradius (r) ändern",
		"ellipse_cx": "Ellipsenzentrum (cx) ändern",
		"ellipse_cy": "Ellipsenzentrum (cy) ändern",
		"ellipse_rx": "Ellipsenradius (x) ändern",
		"ellipse_ry": "Ellipsenradius (y) ändern",
		"line_x1": "X-Koordinate des Linienanfangs ändern",
		"line_x2": "X-Koordinate des Linienendes ändern",
		"line_y1": "Y-Koordinate des Linienanfangs ändern",
		"line_y2": "Y-Koordinate des Linienendes ändern",
		"rect_height": "Höhe des Rechtecks ändern",
		"rect_width": "Breite des Rechtecks ändern",
		"corner_radius": "Eckenradius des Rechtecks ändern",
		"image_width": "Bildbreite ändern",
		"image_height": "Bildhöhe ändern",
		"image_url": "URL ändern",
		"node_x": "Ändere die X Koordinate des Knoten",
		"node_y": "Ändere die Y Koordinate des Knoten",
		"seg_type": "Ändere den Typ des Segments",
		"straight_segments": "Gerade",
		"curve_segments": "Kurve",
		"text_contents": "Textinhalt erstellen und bearbeiten",
		"font_family": "Schriftart wählen",
		"font_size": "Schriftgröße einstellen",
		"bold": "Fetter Text",
		"italic": "Kursiver Text"
	},
	tools: {
		"main_menu": "Hauptmenü",
		"bkgnd_color_opac": "Hintergrundfarbe ändern / Opazität",
		"connector_no_arrow": "Kein Pfeil",
		"fitToContent": "An den Inhalt anpassen",
		"fit_to_all": "An gesamten Inhalt anpassen",
		"fit_to_canvas": "An die Zeichenfläche anpassen",
		"fit_to_layer_content": "An Inhalt der Ebene anpassen",
		"fit_to_sel": "An die Auswahl anpassen",
		"align_relative_to": "Relativ zu einem anderem Objekt ausrichten ...",
		"relativeTo": "im Vergleich zu:",
		"Seite": "Seite",
		"largest_object": "größtes Objekt",
		"selected_objects": "gewählte Objekte",
		"smallest_object": "kleinstes Objekt",
		"new_doc": "Neues Bild",
		"open_doc": "Bild öffnen",
		"export_png": "Als PNG exportieren",
		"save_doc": "Bild speichern",
		"import_doc": "Importiere SVG",
		"align_to_page": "Align Element to Page",
		"align_bottom": "Unten ausrichten",
		"align_center": "Zentriert ausrichten",
		"align_left": "Linksbündig ausrichten",
		"align_middle": "In der Mitte ausrichten",
		"align_right": "Rechtsbündig ausrichten",
		"align_top": "Oben ausrichten",
		"mode_select": "Objekte auswählen und verändern",
		"mode_fhpath": "Freihandlinien zeichnen",
		"mode_line": "Linien zeichnen",
		"mode_connect": "Verbinde zwei Objekte",
		"mode_rect": "Rectangle Tool",
		"mode_square": "Square Tool",
		"mode_fhrect": "Freihand Rechteck",
		"mode_ellipse": "Ellipse",
		"mode_circle": "Kreis",
		"mode_fhellipse": "Freihand Ellipse",
		"mode_path": "Pfad zeichnen",
		"mode_shapelib": "Shape library",
		"mode_text": "Text erstellen und bearbeiten",
		"mode_image": "Bild einfügen",
		"mode_zoom": "Zoomfaktor vergrößern oder verringern",
		"mode_eyedropper": "Ableger",
		"no_embed": "Hinweis: Dieses Bild kann nicht eingebettet werden. Eine Anzeige hängt von diesem Pfad ab.",
		"undo": "Rückgängig",
		"redo": "Wiederherstellen",
		"tool_source": "Quellecode bearbeiten",
		"wireframe_mode": "Drahtmodell Modus",
		"toggle_grid": "Show/Hide Grid",
		"clone": "Clone Element(s)",
		"del": "Delete Element(s)",
		"group": "Gruppieren",
		"make_link": "Make (hyper)link",
		"set_link_url": "Set link URL (leave empty to remove)",
		"to_path": "Gewähltes Objekt in einen Pfad konvertieren",
		"reorient_path": "Neuausrichtung des Pfades",
		"ungroup": "Gruppierung aufheben",
		"docprops": "Dokument-Eigenschaften",
		"imagelib": "Image Library",
		"move_bottom": "Die gewählten Objekte nach ganz unten schieben",
		"move_top": "Die gewählten Objekte nach ganz oben anheben",
		"node_clone": "Klone den Knoten",
		"node_delete": "Lösche den Knoten",
		"node_link": "Gekoppelte oder separate Kontroll Punkte für die Bearbeitung des Pfades",
		"add_subpath": "Teilpfad hinzufügen",
		"openclose_path": "Open/close sub-path",
		"source_save": "Änderungen akzeptieren",
		"cut": "Cut",
		"copy": "Copy",
		"paste": "Paste",
		"paste_in_place": "Paste in Place",
		"Löschen": "Delete",
		"group": "Group",
		"move_front": "Bring to Front",
		"move_up": "Bring Forward",
		"move_down": "Send Backward",
		"move_back": "Send to Back"
	},
	layers: {
		"layer":"Ebene",
		"layers": "Layers",
		"del": "Ebene löschen",
		"move_down": "Ebene nach unten verschieben",
		"new": "Neue Ebene",
		"rename": "Ebene umbenennen",
		"move_up": "Ebene nach oben verschieben",
		"dupe": "Duplicate Layer",
		"merge_down": "Merge Down",
		"merge_all": "Merge All",
		"move_elems_to": "Verschiebe ausgewählte Objekte:",
		"move_selected": "Verschiebe ausgewählte Objekte auf eine andere Ebene"
	},
	config: {
		"image_props": "Bildeigenschaften",
		"doc_title": "Titel",
		"doc_dims": "Dimension der Zeichenfläche",
		"included_images": "Eingefügte Bilder",
		"image_opt_embed": "Daten einbetten (lokale Dateien)",
		"image_opt_ref": "Benutze die Datei Referenz",
		"editor_prefs": "Editor Einstellungen",
		"icon_size": "Symbol Abmessungen",
		"language": "Sprache",
		"background": "Editor Hintergrund",
		"editor_img_url": "Image URL",
		"editor_bg_note": "Anmerkung: Der Hintergrund wird mit der Speicherung des Bildes nicht gespeichert.",
		"icon_large": "Groß",
		"icon_medium": "Mittel",
		"icon_small": "Klein",
		"icon_xlarge": "Sehr Groß",
		"select_predefined": "Auswahl einer vordefinierten:",
		"units_and_rulers": "Units & Rulers",
		"show_rulers": "Show rulers",
		"base_unit": "Base Unit:",
		"grid": "Grid",
		"snapping_onoff": "Snapping on/off",
		"snapping_stepsize": "Snapping Step-Size:",
		"grid_color": "Grid color"
	},
	shape_cats: {
		"basic": "Basic",
		"object": "Objects",
		"symbol": "Symbols",
		"arrow": "Arrows",
		"flowchart": "Flowchart",
		"animal": "Animals",
		"game": "Cards & Chess",
		"dialog_balloon": "Dialog balloons",
		"electronics": "Electronics",
		"math": "Mathematical",
		"music": "Music",
		"misc": "Miscellaneous",
		"raphael_1": "raphaeljs.com set 1",
		"raphael_2": "raphaeljs.com set 2"
	},
	imagelib: {
		"select_lib": "Select an image library",
		"show_list": "Show library list",
		"import_single": "Import single",
		"import_multi": "Import multiple",
		"open": "Open as new document"
	},
	notification: {
		"invalidAttrValGiven":"Fehlerhafter Wert",
		"noContentToFitTo":"Kein Inhalt anzupassen",
		"dupeLayerName":"Eine Ebene hat bereits diesen Namen!",
		"enterUniqueLayerName":"Verwenden Sie einen eindeutigen Namen für die Ebene",
		"enterNewLayerName":"Geben Sie bitte einen neuen Namen für die Ebene ein",
		"layerHasThatName":"Eine Ebene hat bereits diesen Namen",
		"QmoveElemsToLayer":"Verschiebe ausgewählte Objekte in die Ebene '%s'?",
		"QwantToClear":"Möchten Sie die Zeichnung löschen?\nDadurch wird auch die Rückgängig Funktion zurückgesetzt!",
		"QwantToOpen":"Do you want to open a new file?\nThis will also erase your undo history!",
		"QerrorsRevertToSource":"Die Syntaxanalyse Ihrer SVG Quelle enthält Fehler.\nOriginal SVG wiederherstellen?",
		"QignoreSourceChanges":"Soll die Änderung am SVG Quelltext ignoriert werden?",
		"featNotSupported":"Diese Eigenschaft wird nicht unterstützt",
		"enterNewImgURL":"Geben Sie die URL für das neue Bild an",
		"defsFailOnSave": "Hinweis: Aufgrund eines Fehlers in Ihrem Browser, kann dieses Bild falsch angezeigt werden (fehlende Gradienten oder Elemente). Es wird jedoch richtig angezeigt sobald es tatsächlich gespeichert wird.",
		"loadingImage":"Bild wird geladen, bitte warten ...",
		"saveFromBrowser": "Wählen Sie \"Speichern unter ...\" in Ihrem Browser, um das Bild als Datei %s zu speichern.",
		"noteTheseIssues": "Beachten Sie außerdem die folgenden Probleme: ",
		"unsavedChanges": "There are unsaved changes.",
		"enterNewLinkURL": "Enter the new hyperlink URL",
		"errorLoadingSVG": "Error: Unable to load SVG data",
		"URLloadFail": "Unable to load from URL",
		"retrieving": "Retrieving \"%s\"..."
	}
});<commit_msg>closed #1033 - German translation<commit_after>svgEditor.readLang({
	lang: "de",
	dir : "ltr",
	common: {
		"ok": "OK",
		"cancel": "Abbrechen",
		"key_backspace": "Rücktaste",
		"key_del": "Löschen",
		"key_down": "nach unten",
		"key_up": "nach oben",
		"more_opts": "More Options",
		"url": "URL",
		"width": "Breite",
		"height": "Höhe"
	},
	misc: {
		"powered_by": "angetrieben durch"
	},
	ui: {
		"toggle_stroke_tools": "Zeige/Verberge weitere Linien Werkzeuge",
		"palette_info": "Klick zum Ändern der Füllfarbe, Shift-Klick zum Ändern der Linienfarbe",
		"zoom_level": "vergrößern",
		"panel_drag": "Drag left/right to resize side panel"
	},
	properties: {
		"id": "Identify the element",
		"fill_color": "Füllfarbe ändern",
		"stroke_color": "Linienfarbe ändern",
		"stroke_style": "Linienstil ändern",
		"stroke_width": "Linienbreite ändern",
		"pos_x": "Ändere die X Koordinate",
		"pos_y": "Ändere die Y Koordinate",
		"linecap_butt": "Form der Linienendung: Stumpf",
		"linecap_round": "Form der Linienendung: Rund",
		"linecap_square": "Form der Linienendung: Rechteckig",
		"linejoin_bevel": "Zusammentreffen von zwei Linien: abgeschrägte Kante",
		"linejoin_miter": "Zusammentreffen von zwei Linien: Gehrung",
		"linejoin_round": "Zusammentreffen von zwei Linien: Rund",
		"angle": "Drehwinkel ändern",
		"blur": "Ändere Gaußschen Weichzeichner Wert",
		"opacity": "Opazität des ausgewählten Objekts ändern",
		"circle_cx": "Kreiszentrum (cx) ändern",
		"circle_cy": "Kreiszentrum (cy) ändern",
		"circle_r": "Kreisradius (r) ändern",
		"ellipse_cx": "Ellipsenzentrum (cx) ändern",
		"ellipse_cy": "Ellipsenzentrum (cy) ändern",
		"ellipse_rx": "Ellipsenradius (x) ändern",
		"ellipse_ry": "Ellipsenradius (y) ändern",
		"line_x1": "X-Koordinate des Linienanfangs ändern",
		"line_x2": "X-Koordinate des Linienendes ändern",
		"line_y1": "Y-Koordinate des Linienanfangs ändern",
		"line_y2": "Y-Koordinate des Linienendes ändern",
		"rect_height": "Höhe des Rechtecks ändern",
		"rect_width": "Breite des Rechtecks ändern",
		"corner_radius": "Eckenradius des Rechtecks ändern",
		"image_width": "Bildbreite ändern",
		"image_height": "Bildhöhe ändern",
		"image_url": "URL ändern",
		"node_x": "Ändere die X Koordinate des Knoten",
		"node_y": "Ändere die Y Koordinate des Knoten",
		"seg_type": "Ändere den Typ des Segments",
		"straight_segments": "Gerade",
		"curve_segments": "Kurve",
		"text_contents": "Textinhalt erstellen und bearbeiten",
		"font_family": "Schriftart wählen",
		"font_size": "Schriftgröße einstellen",
		"bold": "Fetter Text",
		"italic": "Kursiver Text"
	},
	tools: {
		"main_menu": "Hauptmenü",
		"bkgnd_color_opac": "Hintergrundfarbe ändern / Opazität",
		"connector_no_arrow": "Kein Pfeil",
		"fitToContent": "An den Inhalt anpassen",
		"fit_to_all": "An gesamten Inhalt anpassen",
		"fit_to_canvas": "An die Zeichenfläche anpassen",
		"fit_to_layer_content": "An Inhalt der Ebene anpassen",
		"fit_to_sel": "An die Auswahl anpassen",
		"align_relative_to": "Relativ zu einem anderem Objekt ausrichten ...",
		"relativeTo": "im Vergleich zu:",
		"Seite": "Seite",
		"largest_object": "größtes Objekt",
		"selected_objects": "gewählte Objekte",
		"smallest_object": "kleinstes Objekt",
		"new_doc": "Neues Bild",
		"open_doc": "Bild öffnen",
		"export_png": "Als PNG exportieren",
		"save_doc": "Bild speichern",
		"import_doc": "Importiere SVG",
		"align_to_page": "Align Element to Page",
		"align_bottom": "Unten ausrichten",
		"align_center": "Zentriert ausrichten",
		"align_left": "Linksbündig ausrichten",
		"align_middle": "In der Mitte ausrichten",
		"align_right": "Rechtsbündig ausrichten",
		"align_top": "Oben ausrichten",
		"mode_select": "Objekte auswählen und verändern",
		"mode_fhpath": "Freihandlinien zeichnen",
		"mode_line": "Linien zeichnen",
		"mode_connect": "Verbinde zwei Objekte",
		"mode_rect": "Rectangle Tool",
		"mode_square": "Square Tool",
		"mode_fhrect": "Freihand Rechteck",
		"mode_ellipse": "Ellipse",
		"mode_circle": "Kreis",
		"mode_fhellipse": "Freihand Ellipse",
		"mode_path": "Pfad zeichnen",
		"mode_shapelib": "Form-Bibliothek",
		"mode_text": "Text erstellen und bearbeiten",
		"mode_image": "Bild einfügen",
		"mode_zoom": "Zoomfaktor vergrößern oder verringern",
		"mode_eyedropper": "Ableger",
		"no_embed": "Hinweis: Dieses Bild kann nicht eingebettet werden. Eine Anzeige hängt von diesem Pfad ab.",
		"undo": "Rückgängig",
		"redo": "Wiederherstellen",
		"tool_source": "Quellecode bearbeiten",
		"wireframe_mode": "Drahtmodell Modus",
		"toggle_grid": "Zeige/Verstecke Gitternetz",
		"clone": "Klone Element(e)",
		"del": "Lösche Element(e)",
		"group": "Gruppieren",
		"make_link": "Make (hyper)link",
		"set_link_url": "Set link URL (leave empty to remove)",
		"to_path": "Gewähltes Objekt in einen Pfad konvertieren",
		"reorient_path": "Neuausrichtung des Pfades",
		"ungroup": "Gruppierung aufheben",
		"docprops": "Dokument-Eigenschaften",
		"imagelib": "Bilder-Bibliothek",
		"move_bottom": "Die gewählten Objekte nach ganz unten schieben",
		"move_top": "Die gewählten Objekte nach ganz oben anheben",
		"node_clone": "Klone den Knoten",
		"node_delete": "Lösche den Knoten",
		"node_link": "Gekoppelte oder separate Kontroll Punkte für die Bearbeitung des Pfades",
		"add_subpath": "Teilpfad hinzufügen",
		"openclose_path": "Öffne/Verbinde Unterpfad",
		"source_save": "Änderungen akzeptieren",
		"cut": "Ausschneiden",
		"copy": "Kopieren",
		"paste": "Einfügen",
		"paste_in_place": "An Originalposition einfügen",
		"Löschen": "Löschen",
		"move_front": "Nach ganz oben anheben",
		"move_up": "Anheben",
		"move_down": "Absenken",
		"move_back": "Nach ganz unten absenken"
	},
	layers: {
		"layer": "Ebene",
		"layers": "Ebenen",
		"del": "Ebene löschen",
		"move_down": "Ebene nach unten verschieben",
		"new": "Neue Ebene",
		"rename": "Ebene umbenennen",
		"move_up": "Ebene nach oben verschieben",
		"dupe": "Duplicate Layer",
		"merge_down": "Merge Down",
		"merge_all": "Merge All",
		"move_elems_to": "Verschiebe ausgewählte Objekte:",
		"move_selected": "Verschiebe ausgewählte Objekte auf eine andere Ebene"
	},
	config: {
		"image_props": "Bildeigenschaften",
		"doc_title": "Titel",
		"doc_dims": "Dimension der Zeichenfläche",
		"included_images": "Eingefügte Bilder",
		"image_opt_embed": "Daten einbetten (lokale Dateien)",
		"image_opt_ref": "Benutze die Datei Referenz",
		"editor_prefs": "Editor Einstellungen",
		"icon_size": "Symbol Abmessungen",
		"language": "Sprache",
		"background": "Editor Hintergrund",
		"editor_img_url": "Image URL",
		"editor_bg_note": "Anmerkung: Der Hintergrund wird mit der Speicherung des Bildes nicht gespeichert.",
		"icon_large": "Groß",
		"icon_medium": "Mittel",
		"icon_small": "Klein",
		"icon_xlarge": "Sehr Groß",
		"select_predefined": "Auswahl einer vordefinierten:",
		"units_and_rulers": "Einheiten und Lineale",
		"show_rulers": "Zeige Lineale",
		"base_unit": "Basiseinheit:",
		"grid": "Gitternetz",
		"snapping_onoff": "Einrasten an/aus",
		"snapping_stepsize": "Einrastungs Abstand:",
		"grid_color": "Grid color"
	},
	shape_cats: {
		"basic": "Standard",
		"object": "Objekte",
		"symbol": "Symbole",
		"arrow": "Pfeile",
		"flowchart": "Flussdiagramme",
		"animal": "Tiere",
		"game": "Spielkarten und Schach",
		"dialog_balloon": "Sprechblasen",
		"electronics": "Elektronik",
		"math": "Mathematik",
		"music": "Musik",
		"misc": "Sonstige",
		"raphael_1": "raphaeljs.com set 1",
		"raphael_2": "raphaeljs.com set 2"
	},
	imagelib: {
		"select_lib": "Select an image library",
		"show_list": "Show library list",
		"import_single": "Import single",
		"import_multi": "Import multiple",
		"open": "Open as new document"
	},
	notification: {
		"invalidAttrValGiven":"Fehlerhafter Wert",
		"noContentToFitTo":"Kein Inhalt anzupassen",
		"dupeLayerName":"Eine Ebene hat bereits diesen Namen!",
		"enterUniqueLayerName":"Verwenden Sie einen eindeutigen Namen für die Ebene",
		"enterNewLayerName":"Geben Sie bitte einen neuen Namen für die Ebene ein",
		"layerHasThatName":"Eine Ebene hat bereits diesen Namen",
		"QmoveElemsToLayer":"Verschiebe ausgewählte Objekte in die Ebene '%s'?",
		"QwantToClear":"Möchten Sie die Zeichnung löschen?\nDadurch wird auch die Rückgängig Funktion zurückgesetzt!",
		"QwantToOpen":"Do you want to open a new file?\nThis will also erase your undo history!",
		"QerrorsRevertToSource":"Die Syntaxanalyse Ihrer SVG Quelle enthält Fehler.\nOriginal SVG wiederherstellen?",
		"QignoreSourceChanges":"Soll die Änderung am SVG Quelltext ignoriert werden?",
		"featNotSupported":"Diese Eigenschaft wird nicht unterstützt",
		"enterNewImgURL":"Geben Sie die URL für das neue Bild an",
		"defsFailOnSave": "Hinweis: Aufgrund eines Fehlers in Ihrem Browser, kann dieses Bild falsch angezeigt werden (fehlende Gradienten oder Elemente). Es wird jedoch richtig angezeigt sobald es tatsächlich gespeichert wird.",
		"loadingImage":"Bild wird geladen, bitte warten ...",
		"saveFromBrowser": "Wählen Sie \"Speichern unter ...\" in Ihrem Browser, um das Bild als Datei %s zu speichern.",
		"noteTheseIssues": "Beachten Sie außerdem die folgenden Probleme: ",
		"unsavedChanges": "There are unsaved changes.",
		"enterNewLinkURL": "Enter the new hyperlink URL",
		"errorLoadingSVG": "Error: Unable to load SVG data",
		"URLloadFail": "Unable to load from URL",
		"retrieving": "Retrieving \"%s\"..."
	}
});<|endoftext|>


<commit_before>[
{"id":"layer_new","title":"Nieuwe laag"},
{"id":"layer_delete","title":"Delete laag"},
{"id":"layer_rename","title":"Hernoem laag"},
{"id":"layer_up","title":"Beweeg laag omhoog"},
{"id":"layer_down","title":"Beweeg laag omlaag"},
{"id":"tool_clear","title":"Nieuwe afbeelding"},
{"id":"tool_open","title":"Open afbeelding"},
{"id":"tool_save","title":"Afbeelding opslaan"},
{"id":"tool_docprops","title":"Documenteigenschappen"},
{"id":"tool_source","title":"Bewerk bron"},
{"id":"tool_undo","title":"Ongedaan maken"},
{"id":"tool_redo","title":"Opnieuw doen"},
{"id":"tool_clone","title":"Kloon element"},
{"id":"tool_delete","title":"Delete element"},
{"id":"tool_move_top","title":"Naar voorgrond"},
{"id":"tool_move_bottom","title":"Naar achtergrond"},
{"id":"group_opacity","title":"Verander opaciteit geselecteerde item"},
{"id":"angle","title":"Draai"},
{"id":"tool_clone_multi","title":"Kloon elementen"},
{"id":"tool_delete_multi","title":"Delete geselecteerde elementen"},
{"id":"tool_alignleft","title":"Links uitlijnen"},
{"id":"tool_aligncenter","title":"Centreren"},
{"id":"tool_alignright","title":"Rechts uitlijnen"},
{"id":"tool_aligntop","title":"Boven uitlijnen"},
{"id":"tool_alignmiddle","title":"Midden uitlijnen"},
{"id":"tool_alignbottom","title":"Onder uitlijnen"},
{"id":"align_relative_to","title":"Uitlijnen relatief ten opzichte van ..."},
{"id":"tool_group","title":"Groepeer elementen"},
{"id":"tool_ungroup","title":"Groepering opheffen"},
{"id":"rect_width","title":"Verander breedte rechthoek"},
{"id":"rect_height","title":"Verander hoogte rechthoek"},
{"id":"rect_rx","title":"Verander hoek radius rechthoek"},
{"id":"image_width","title":"Verander breedte afbeelding"},
{"id":"image_height","title":"Verander hoogte afbeelding"},
{"id":"image_url","title":"Verander URL"},
{"id":"circle_cx" ,"title":"Verander het X coordinaat van het cirkel centrum"},
{"id":"circle_cy" ,"title":"Verander het Y coordinaat van het cirkel centrum"},
{"id":"circle_r","title":"Verander de cirkel radius"},
{"id":"ellipse_cx","title":"Verander het X coordinaat van het ellips centrum"},
{"id":"ellipse_cy","title":"Verander het Y coordinaat van het ellips centrum"},
{"id":"ellipse_rx","title":"Verander ellips X radius"},
{"id":"ellipse_ry","title":"Verander ellips Y radius"},
{"id":"line_x1","title":"Verander regel start X coordinaat"},
{"id":"line_y1","title":"Verander regel start Y coordinaat"},
{"id":"line_x2","title":"Verander regel eind X coordinaat"},
{"id":"line_y2","title":"Verander regel eind Y coordinaat"},
{"id":"tool_bold","title":"Vet"},
{"id":"tool_italic","title":"Cursief"},
{"id":"font_family","title":"Verander lettertype"},
{"id":"font_size","title":"Verander lettertype grootte"},
{"id":"text","title":"Wijzig tekst"},
{"id":"tool_select","title":"Selecteer"},
{"id":"tool_fhpath","title":"Potlood"},
{"id":"tool_line","title":"Lijn"},
{"id":"tools_rect_show","title":"Vierkant/rechthoek"},
{"id":"tools_ellipse_show","title":"Ellips/cirkel"},
{"id":"tool_text","title":"Tekst"},
{"id":"tool_path","title":"Pad"},
{"id":"tool_image","title":"Afbeelding"},
{"id":"tool_zoom","title":"Zoom"},
{"id":"zoom","title":"In-/uitzoomen"},
{"id":"fill_color","title":"Verander vul kleur"},
{"id":"stroke_color","title":"Verander lijn kleur"},
{"id":"stroke_width","title":"Verander lijn breedte"},
{"id":"stroke_style","title":"Verander lijn stijl"},
{"id":"palette","title":"Klik om de vul kleur te veranderen, shift-klik om de lijn kleur te veranderen"},
{"id":"tool_square","title":"Vierkant"},
{"id":"tool_rect","title":"Rechthoek"},
{"id":"tool_fhrect","title":"Vrije stijl rechthoek"},
{"id":"tool_circle","title":"Cirkel"},
{"id":"tool_ellipse","title":"Ellips"},
{"id":"tool_fhellipse","title":"Vrije stijl ellips"},
{"id":"bkgnd_color","title":"Verander achtergrond kleur/doorzichtigheid"},
{"id":"rwidthLabel","textContent":"Breedte:"},
{"id":"rheightLabel","textContent":"Hoogte:"},
{"id":"cornerRadiusLabel","textContent":"Hoek radius:"},
{"id":"iwidthLabel","textContent":"Breedte:"},
{"id":"iheightLabel","textContent":"Hoogte:"},
{"id":"svginfo_width","textContent":"Breedte:" },
{"id":"svginfo_height","textContent":"Hoogte:" },
{"id":"angleLabel","textContent":"Hoek:"},
{"id":"relativeToLabel","textContent":"Relatief ten opzichte van:"},
{"id":"zoomLabel","textContent":"Zoom:"},
{"id":"layersLabel","textContent":"Lagen:"},
{"id":"selectedPredefined","textContent":"Kies voorgedefinieerd:"},
{"id":"fitToContent","textContent":"Pas om inhoud"},
{"id":"tool_source_save","textContent":"Veranderingen toepassen"},
{"id":"tool_docprops_save","textContent":"OK"},
{"id":"tool_docprops_cancel","textContent":"Annuleren"},
{"id":"tool_source_cancel","textContent":"Annuleren"},
{"id":"fit_to_all","textContent":"Pas om alle inhoud"},
{"id":"fit_to_layer_content" ,"textContent":"Pas om laag inhoud"},
{"id":"fit_to_sel","textContent":"Pas om selectie"},
{"id":"fit_to_canvas","textContent":"Pas om canvas"},
{"id":"selected_objects","textContent":"Geselecteerde objecten"},
{"id":"largest_object","textContent":"Grootste object"},
{"id":"smallest_object","textContent":"Kleinste object"},
{"id":"page","textContent":"Pagina"},
{"id":"fill_tool_bottom","textContent":"Vull:"},
{"id":"stroke_tool_bottom","textContent":"(om)lijn(ing):"},
{"id":"path_node_x","title":"Verander X coordinaat knooppunt"},
{"id":"path_node_y","title":"Verander Y coordinaat knooppunt"},
{"id":"seg_type","title":"Verander segment type"},
{"id":"straight_segments","textContent":"Recht"},
{"id":"curve_segments","textContent":"Gebogen"},
{"id":"tool_node_clone","title":"Kloon knooppunt"},
{"id":"tool_node_delete","title":"Delete knooppunt"},
{"id":"selLayerLabel","textContent":"Verplaats elementen naar:"},
{"id":"selLayerNames","title":"Verplaats geselecteerde elementen naar andere laag"},
{"id":"sidepanel_handle","title":"Sleep naar links/rechts om het zijpaneel te vergroten/verkleinen","textContent":"L a g e n"},
{"id":"tool_wireframe","title":"'Wireframe' mode"},
{"id":"svginfo_image_props","textContent":"Afbeeldingeigenschappen"},
{"id":"svginfo_title","textContent":"Titel"},
{"id":"svginfo_dim","textContent":"Canvas afmetingen"},
{"id":"includedImages","textContent":"Ingesloten afbeeldingen"},
{"id":"image_opt_embed","textContent":"Toevoegen data (lokale bestanden)"},
{"id":"image_opt_ref","textContent":"Gebruik bestand referentie"},
{"id":"svginfo_editor_prefs","textContent":"Editor eigenschappen"},
{"id":"svginfo_lang","textContent":"Taal"},
{"id":"svginfo_change_background","textContent":"Editor achtergrond"},
{"id":"svginfo_bg_note","textContent":"Let op: De achtergrond wordt niet opgeslagen met de afbeelding."},
{"id":"svginfo_icons","textContent":"Icoon grootte"},
{"id":"icon_small","textContent":"Klein"},
{"id":"icon_medium","textContent":"Gemiddeld"},
{"id":"icon_large","textContent":"Groot"},
{"id":"icon_xlarge","textContent":"Extra groot"},
{"id":"selected_x","title":"Verander X coordinaat"},
{"id":"selected_y","title":"Verander Y coordinaat"},
{"id":"tool_topath","title":"Zet om naar lijnen"},
{"id":"tool_reorient","title":"Herorienteer pad"},
{"id":"tool_node_link","title":"Koppel controlle punten"},
{"js_strings": {
		"invalidAttrValGiven":"Verkeerde waarde gegeven",
		"noContentToFitTo":"Geen inhoud om omheen te passen",
		'layer':"Laag",
		"dupeLayerName":"Er is al een laag met die naam!",
		"enterUniqueLayerName":"Geef een unieke laag naam",
		"enterNewLayerName":"Geef een nieuwe laag naam",
		"layerHasThatName":"Laag heeft al die naam",
		"QmoveElemsToLayer":"Verplaats geselecteerde elementen naar laag '%s'?",
		"QwantToClear":"Wil je de afbeelding leeg maken?\nDit zal ook de ongedaan maak geschiedenis wissen!",
		"QerrorsRevertToSource":"Er waren analyse fouten in je SVG bron.\nTeruggaan naar de originele SVG bron?",
		"QignoreSourceChanges":"Veranderingen in de SVG bron negeren?",
		"featNotSupported":"Functie wordt niet ondersteund",
		"enterNewImgURL":"Geef de nieuwe afbeelding URL",
		"ok":"OK",
		"cancel":"Annuleren",
		"pathNodeTooltip":"Versleep knooppunt om hem te verslepen. Dubbel klik knooppunt om het segment type te veranderen",
		"pathCtrlPtTooltip":"Versleep het controlle punt om de boog eigenschappen te veranderen",
		"key_up":"omhoog",
		"key_down":"omlaag",
		"key_backspace":"backspace",
		"key_del":"delete"
	}
}
];
<commit_msg>Update the Dutch translation by Jaap Blom.<commit_after>[
{"id":"layer_new","title":"Nieuwe laag"},
{"id":"layer_delete","title":"Delete laag"},
{"id":"layer_rename","title":"Hernoem laag"},
{"id":"layer_up","title":"Beweeg laag omhoog"},
{"id":"layer_down","title":"Beweeg laag omlaag"},
{"id":"tool_clear","title":"Nieuwe afbeelding"},
{"id":"tool_open","title":"Open afbeelding"},
{"id":"tool_save","title":"Afbeelding opslaan"},
{"id":"tool_docprops","title":"Documenteigenschappen"},
{"id":"tool_source","title":"Bewerk bron"},
{"id":"tool_undo","title":"Ongedaan maken"},
{"id":"tool_redo","title":"Opnieuw doen"},
{"id":"tool_clone","title":"Kloon element"},
{"id":"tool_delete","title":"Delete element"},
{"id":"tool_move_top","title":"Naar voorgrond"},
{"id":"tool_move_bottom","title":"Naar achtergrond"},
{"id":"group_opacity","title":"Verander opaciteit geselecteerde item"},
{"id":"angle","title":"Draai"},
{"id":"tool_clone_multi","title":"Kloon elementen"},
{"id":"tool_delete_multi","title":"Delete geselecteerde elementen"},
{"id":"tool_alignleft","title":"Links uitlijnen"},
{"id":"tool_aligncenter","title":"Centreren"},
{"id":"tool_alignright","title":"Rechts uitlijnen"},
{"id":"tool_aligntop","title":"Boven uitlijnen"},
{"id":"tool_alignmiddle","title":"Midden uitlijnen"},
{"id":"tool_alignbottom","title":"Onder uitlijnen"},
{"id":"align_relative_to","title":"Uitlijnen relatief ten opzichte van ..."},
{"id":"tool_group","title":"Groepeer elementen"},
{"id":"tool_ungroup","title":"Groepering opheffen"},
{"id":"rect_width","title":"Verander breedte rechthoek"},
{"id":"rect_height","title":"Verander hoogte rechthoek"},
{"id":"rect_rx","title":"Verander hoekradius rechthoek"},
{"id":"image_width","title":"Verander breedte afbeelding"},
{"id":"image_height","title":"Verander hoogte afbeelding"},
{"id":"image_url","title":"Verander URL"},
{"id":"circle_cx" ,"title":"Verander het X coordinaat van het cirkel middelpunt"},
{"id":"circle_cy" ,"title":"Verander het Y coordinaat van het cirkel middelpunt"},
{"id":"circle_r","title":"Verander de cirkel radius"},
{"id":"ellipse_cx","title":"Verander het X coordinaat van het ellips middelpunt"},
{"id":"ellipse_cy","title":"Verander het Y coordinaat van het ellips middelpunt"},
{"id":"ellipse_rx","title":"Verander ellips X radius"},
{"id":"ellipse_ry","title":"Verander ellips Y radius"},
{"id":"line_x1","title":"Verander start X coordinaat van de lijn"},
{"id":"line_y1","title":"Verander start Y coordinaat van de lijn"},
{"id":"line_x2","title":"Verander eind X coordinaat van de lijn"},
{"id":"line_y2","title":"Verander eind Y coordinaat van de lijn"},
{"id":"tool_bold","title":"Vet"},
{"id":"tool_italic","title":"Cursief"},
{"id":"font_family","title":"Verander lettertype"},
{"id":"font_size","title":"Verander lettertype grootte"},
{"id":"text","title":"Wijzig tekst"},
{"id":"tool_select","title":"Selecteer"},
{"id":"tool_fhpath","title":"Potlood"},
{"id":"tool_line","title":"Lijn"},
{"id":"tools_rect_show","title":"Vierkant/rechthoek"},
{"id":"tools_ellipse_show","title":"Ellips/cirkel"},
{"id":"tool_text","title":"Tekst"},
{"id":"tool_path","title":"Pad"},
{"id":"tool_image","title":"Afbeelding"},
{"id":"tool_zoom","title":"Zoom"},
{"id":"zoom","title":"In-/uitzoomen"},
{"id":"fill_color","title":"Verander vul kleur"},
{"id":"stroke_color","title":"Verander lijn kleur"},
{"id":"stroke_width","title":"Verander lijn breedte"},
{"id":"stroke_style","title":"Verander lijn stijl"},
{"id":"palette","title":"Klik om de vul kleur te veranderen, shift-klik om de lijn kleur te veranderen"},
{"id":"tool_square","title":"Vierkant"},
{"id":"tool_rect","title":"Rechthoek"},
{"id":"tool_fhrect","title":"Vrije stijl rechthoek"},
{"id":"tool_circle","title":"Cirkel"},
{"id":"tool_ellipse","title":"Ellips"},
{"id":"tool_fhellipse","title":"Vrije stijl ellips"},
{"id":"bkgnd_color","title":"Verander achtergrond kleur/doorzichtigheid"},
{"id":"rwidthLabel","textContent":"Breedte:"},
{"id":"rheightLabel","textContent":"Hoogte:"},
{"id":"cornerRadiusLabel","textContent":"Hoek radius:"},
{"id":"iwidthLabel","textContent":"Breedte:"},
{"id":"iheightLabel","textContent":"Hoogte:"},
{"id":"svginfo_width","textContent":"Breedte:"},
{"id":"svginfo_height","textContent":"Hoogte:"},
{"id":"angleLabel","textContent":"Hoek:"},
{"id":"relativeToLabel","textContent":"Relatief ten opzichte van:"},
{"id":"zoomLabel","textContent":"Zoom:"},
{"id":"layersLabel","textContent":"Lagen:"},
{"id":"selectedPredefined","textContent":"Kies voorgedefinieerd:"},
{"id":"fitToContent","textContent":"Pas om inhoud"},
{"id":"tool_source_save","textContent":"Veranderingen toepassen"},
{"id":"tool_docprops_save","textContent":"Ok"},
{"id":"tool_docprops_cancel","textContent":"Annuleren"},
{"id":"tool_source_cancel","textContent":"Annuleren"},
{"id":"fit_to_all","textContent":"Pas om alle inhoud"},
{"id":"fit_to_layer_content" ,"textContent":"Pas om laag inhoud"},
{"id":"fit_to_sel","textContent":"Pas om selectie"},
{"id":"fit_to_canvas","textContent":"Pas om canvas"},
{"id":"selected_objects","textContent":"Geselecteerde objecten"},
{"id":"largest_object","textContent":"Grootste object"},
{"id":"smallest_object","textContent":"Kleinste object"},
{"id":"page","textContent":"Pagina"},
{"id":"fill_tool_bottom","textContent":"Vulkleur:"},
{"id":"stroke_tool_bottom","textContent":"Omlijning:"},
{"id":"path_node_x","title":"Verander X coordinaat knooppunt"},
{"id":"path_node_y","title":"Verander Y coordinaat knooppunt"},
{"id":"seg_type","title":"Verander segment type"},
{"id":"straight_segments","textContent":"Recht"},
{"id":"curve_segments","textContent":"Gebogen"},
{"id":"tool_node_clone","title":"Kloon knooppunt"},
{"id":"tool_node_delete","title":"Delete knooppunt"},
{"id":"selLayerLabel","textContent":"Verplaats elementen naar:"},
{"id":"selLayerNames","title":"Verplaats geselecteerde elementen naar andere laag"},
{"id":"sidepanel_handle","title":"Sleep naar links/rechts om het zijpaneel te vergroten/verkleinen","textContent":"L a g e n"},
{"id":"tool_wireframe","title":"Draadmodel"},
{"id":"svginfo_image_props","textContent":"Afbeeldingeigenschappen"},
{"id":"svginfo_title","textContent":"Titel"},
{"id":"svginfo_dim","textContent":"Canvas afmetingen"},
{"id":"includedImages","textContent":"Ingesloten afbeeldingen"},
{"id":"image_opt_embed","textContent":"Toevoegen data (lokale bestanden)"},
{"id":"image_opt_ref","textContent":"Gebruik bestand referentie"},
{"id":"svginfo_editor_prefs","textContent":"Editor eigenschappen"},
{"id":"svginfo_lang","textContent":"Taal"},
{"id":"svginfo_change_background","textContent":"Editor achtergrond"},
{"id":"svginfo_bg_note","textContent":"Let op: De achtergrond wordt niet opgeslagen met de afbeelding."},
{"id":"svginfo_icons","textContent":"Icoon grootte"},
{"id":"icon_small","textContent":"Klein"},
{"id":"icon_medium","textContent":"Gemiddeld"},
{"id":"icon_large","textContent":"Groot"},
{"id":"icon_xlarge","textContent":"Extra groot"},
{"id":"selected_x","title":"Verander X coordinaat"},
{"id":"selected_y","title":"Verander Y coordinaat"},
{"id":"tool_topath","title":"Zet om naar pad"},
{"id":"tool_reorient","title":"Herorienteer pad"},
{"id":"tool_node_link","title":"Koppel controle punten"},
{"js_strings": {
		"invalidAttrValGiven":"Verkeerde waarde gegeven",
		"noContentToFitTo":"Geen inhoud om omheen te passen",
		'layer':"Laag",
		"dupeLayerName":"Er is al een laag met die naam!",
		"enterUniqueLayerName":"Geef een unieke laag naam",
		"enterNewLayerName":"Geef een nieuwe laag naam",
		"layerHasThatName":"Laag heeft al die naam",
		"QmoveElemsToLayer":"Verplaats geselecteerde elementen naar laag '%s'?",
		"QwantToClear":"Wil je de afbeelding leeg maken?\nDit zal ook de ongedaan maak geschiedenis wissen!",
		"QerrorsRevertToSource":"Er waren analyse fouten in je SVG bron.\nTeruggaan naar de originele SVG bron?",
		"QignoreSourceChanges":"Veranderingen in de SVG bron negeren?",
		"featNotSupported":"Functie wordt niet ondersteund",
		"enterNewImgURL":"Geef de nieuwe afbeelding URL",
		"ok":"Ok",
		"cancel":"Annuleren",
		"pathNodeTooltip":"Versleep knooppunt om hem te verslepen. Dubbel klik knooppunt om het segment type te veranderen",
		"pathCtrlPtTooltip":"Versleep het controle punt om de boog eigenschappen te veranderen",
		"key_up":"omhoog",
		"key_down":"omlaag",
		"key_backspace":"backspace",
		"key_del":"delete"
	}
}
];
<|endoftext|>


<commit_before>var	fs = require("fs"),
		S = require("string"),
		util = require("util"),
		path = require("path"),
		Pc = require("postcode"),
		async = require("async"),
		OSPoint = require("ospoint"),
		Base = require("./index").Base;

var postcodeSchema = {
	"id": "SERIAL PRIMARY KEY",
	"postcode" : "VARCHAR(10)",
	"pc_compact" : "VARCHAR(9)",
	"quality" : "INTEGER",
	"eastings" : "INTEGER",
	"northings" : "INTEGER",
	"country" : "VARCHAR(255)",
	"nhs_ha" : "VARCHAR(255)",
	"admin_county" : "VARCHAR(255)",
	"admin_district" : "VARCHAR(255)",
	"admin_ward" : "VARCHAR(255)",
	"longitude" : "DOUBLE PRECISION",
	"latitude" : "DOUBLE PRECISION",
	"location" : "GEOGRAPHY(Point, 4326)",
	"parliamentary_constituency" : "VARCHAR(255)",
	"european_electoral_region" : "VARCHAR(255)",
	"primary_care_trust" : "VARCHAR(255)",
	"region" : "VARCHAR(255)",
	"parish" : "VARCHAR(255)",
	"lsoa" : "VARCHAR(255)",
	"msoa" : "VARCHAR(255)",
	"nuts" : "VARCHAR(255)",
	"incode" : "VARCHAR(5)",
	"outcode" : "VARCHAR(5)",
	"ccg" : "VARCHAR(255)"
};

var indexes = [{
	unique: true,
	column: "postcode"
}, {
	unique: true,
	column: "pc_compact",
	opClass: "varchar_pattern_ops"
}, {
	type: "GIST",
	column: "location"
}, {
	column: "outcode"
}];

function Postcode () {
	Base.call(this, "postcodes", postcodeSchema, indexes);
}

util.inherits(Postcode, Base);

Postcode.prototype.find = function (postcode, callback) {
	if (typeof postcode !== "string") {
		return callback(null, null);
	}

	postcode = postcode.trim().toUpperCase();

	if (!new Pc(postcode).valid()) {
		return callback(null, null);
	}

	var query = "SELECT * FROM " + this.relation + " WHERE pc_compact=$1";

	this._query(query, [postcode.replace(" ", "")], function(error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		callback(null, result.rows[0]);
	});
}

Postcode.prototype.random = function (callback) {
	var query	=	"SELECT * FROM  ("+
					    "SELECT 1 + floor(random() * (SELECT count(id) FROM postcodes))::integer AS id "+
					    "FROM   generate_series(1, 100) g "+
					    "GROUP BY 1 "+
					    ") r "+
							"JOIN postcodes USING (id) "+
							"LIMIT  1;"

	this._query(query, function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		callback(null, result.rows[0]);
	});
}

Postcode.prototype.populateLocation = function (callback) {
	var query = "UPDATE postcodes SET location=ST_GeogFromText" +
							"('SRID=4326;POINT(' || longitude || ' ' || latitude || ')')" +
							" WHERE northings!=0 AND EASTINGS!=0";
	this._query(query, callback);
}

Postcode.prototype.search = function (postcode, options, callback) {
	var limit;
	if (typeof options === 'function') {
		callback = options;
		limit = 10;
	} else {
		limit = parseInt(options.limit, 10);
		if (isNaN(limit)) limit = 10;
		if (limit > 100) limit = 100;
	}

	var	query = "SELECT * FROM postcodes WHERE pc_compact ~ $1 LIMIT $2",
			re = "^" + postcode.toUpperCase().replace(" ", "") + ".*";

	this._query(query, [re, limit], function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		return callback(null, result.rows);
	});
}

Postcode.prototype.nearestPostcodes = function (params, callback) {
	var radius = parseFloat(params.radius) || 100;
	if (radius > 1000) radius = 1000;

	var limit = parseInt(params.limit, 10) || 10;
	if (limit > 100) limit = 100;

	var longitude = parseFloat(params.longitude);
	if (isNaN(longitude)) return callback(new Error("Invalid longitude"), null);

	var latitude = parseFloat(params.latitude);
	if (isNaN(latitude)) return callback(new Error("Invalid latitude"), null);

	var query = "SELECT *, ST_Distance(location, " +
							" ST_GeographyFromText('POINT(' || $1 || ' ' || $2 || ')')) AS distance " +
							"FROM postcodes " +
							"WHERE ST_DWithin(location, ST_GeographyFromText('POINT(' || $1 || ' ' || $2 || ')'), $3) " +
							"ORDER BY distance LIMIT $4";
	this._query(query, [longitude, latitude, radius, limit], function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		return callback(null, result.rows);
	});
}

Postcode.prototype.findOutcode = function (outcode, callback) {
	outcode = outcode.trim().toUpperCase();

	if (!Pc.validOutcode(outcode)) {
		return callback(null, null);
	}

	var query = "Select avg(northings) as northings, avg(eastings) as eastings, " +
							"avg(ST_X(location::geometry)) as longitude, avg(ST_Y(location::geometry))" +
							" as latitude FROM postcodes WHERE postcodes.outcode=$1";

	this._query(query, [outcode], function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length !== 1) return callback(null, null);
		var outcodeResult = result.rows[0];
		if (!outcodeResult.eastings || !outcodeResult.northings) {
			return callback(null, null);
		}
		outcodeResult.outcode = outcode;
		return callback(null, result.rows[0]);
	});
}

Postcode.prototype.toJson = function (address) {
	delete address.id;
	delete address.location;
	delete address.pc_compact;
	return address;
}

/*
*  	ONS CSV Data Reference
*
*		0 - Unit postcode (7char)
*		1 - Unit postcode (8char)
*		2 - Unit postcode (variable)											Y
*		3 - Date of intro
*		4 - Date of termination (null = live)
*		5 - County 																				Y
*		6 - District 																			Y
*		7 - Ward 																					Y
*		8 - Postcode user type (small/large)
*		9 - Easting 																			Y
*		10 - Northings 																		Y
*		11 - Positional quality indicator 								Y
*		12 - Strategic health authority (SHA) (nhs_ha) 		Y
*		13 - Pan SHA (nhs_regional)
*		14 - Country 																			Y
*		15 - Region (region code, GOR)										Y
*		16 - Standard statistical region (SSR)
*		17 - Westminster parliamentary constituency 			Y
*		18 - European Electoral Register									Y
*		19 - Local learning and skills council
*		20 - Travel to work area
*		21 - Primary care trust 													Y
*		22 - NUTS / LAU areas 														Y
*		23 - 1991 census ed
*		24 - 1991 census ed with census code
*		25 - ed positional quality indicator
*		26 - Previous SHA prior to 2006
*		27 - LEA
*		28 - Health Authority (old style)
*		29 - 1991 ward
*		30 - 1991 ward OGSS code
*		31 - 1998 ward
*		32 - 2005 statistical ward
*		33 - 2001 census output area
*		34 - census area statistics ward
*		35 - national park
*		36 - 2001 LSOA
*		37 - 2001 MSOA
*		38 - 2001 rural/urban indicator
*		39 - 2001 OAC
*		40 - Old PCT
*		41 - 2011 census output areas 									Y
*		42 - 2011 LSOA																	Y
*		43 - 2011 MSOA 																	Y
*		44 - Parish 																		Y
*		45 - Census workplace zone
*
*
*/

Postcode.prototype.seedPostcodes = function (filePath, callback) {
	var self = this;
	var csvColumns = 	"postcode, pc_compact, eastings, northings, longitude," +
										" latitude, country, nhs_ha," +
										" admin_county, admin_district, admin_ward, parish, quality," +
										" parliamentary_constituency , european_electoral_region, region, " +
										" primary_care_trust, lsoa, msoa, nuts, incode, outcode, ccg";
	var dataPath = path.join(__dirname, "../../data/");
	var countries = JSON.parse(fs.readFileSync(dataPath + "countries.json"));
	var nhsHa = JSON.parse(fs.readFileSync(dataPath + "nhsHa.json"));
	var counties = JSON.parse(fs.readFileSync(dataPath + "counties.json"));
	var districts = JSON.parse(fs.readFileSync(dataPath + "districts.json"));
	var wards = JSON.parse(fs.readFileSync(dataPath + "wards.json"));
	var parishes = JSON.parse(fs.readFileSync(dataPath + "parishes.json"));
	var constituencies = JSON.parse(fs.readFileSync(dataPath + "constituencies.json"));
	var european_registers = JSON.parse(fs.readFileSync(dataPath + "european_registers.json"));
	var regions = JSON.parse(fs.readFileSync(dataPath + "regions.json"));
	var pcts = JSON.parse(fs.readFileSync(dataPath + "pcts.json"));
	var lsoa = JSON.parse(fs.readFileSync(dataPath + "lsoa.json"));
	var msoa = JSON.parse(fs.readFileSync(dataPath + "msoa.json"));
	var nuts = JSON.parse(fs.readFileSync(dataPath + "nuts.json"));
	var ccg = JSON.parse(fs.readFileSync(dataPath + "ccg.json"));

	var transform = function (row, index) {
		// Skip row if terminated
		if (row[4].length !== 0) {
			return null;
		}

		var finalRow = [];

		finalRow.push(row[2]);  												// postcode
		finalRow.push(row[2].replace(/\s/g, ""));				// pc_compact
		finalRow.push(row[9]);													// Eastings
		finalRow.push(row[10]);													// Northings

		var location;
		if (row[9].length === 0 || row[10].length === 0) {
			location = {
				longitude: "",
				latitude: ""
			};
		} else if (row[14] === "N92000002") {
			location = new OSPoint("" + row[10] , "" + row[9]).toWGS84("irish_national_grid");
		} else {
			location = new OSPoint("" + row[10] , "" + row[9]).toWGS84();
		}

		finalRow.push(location.longitude);							// longitude
		finalRow.push(location.latitude);								// latitude
		finalRow.push(countries[row[14]]);							// Country
		finalRow.push(nhsHa[row[12]]);									// NHS Health Authority
		finalRow.push(counties[row[5]]);								// County
		finalRow.push(districts[row[6]]);								// District
		finalRow.push(wards[row[7]]);										// Ward
		finalRow.push(parishes[row[44]]);								// Parish
		finalRow.push(row[11]);													// Quality
		finalRow.push(constituencies[row[17]]);					// Westminster const.
		finalRow.push(european_registers[row[18]]);			// European electoral region
		finalRow.push(regions[row[15]]);								// Region
		finalRow.push(pcts[row[21]]);										// Primary Care Trusts
		finalRow.push(lsoa[row[42]]);										// 2011 LSOA
		finalRow.push(msoa[row[43]]);										// 2011 MSOA
		finalRow.push(nuts[row[22]]);										// NUTS
		finalRow.push(row[2].split(" ")[1]);						// Incode
		finalRow.push(row[2].split(" ")[0]);						// Outcode
		finalRow.push(ccg[lsoa[row[42]]]);							// Clinical Commissioning Group

		return finalRow;
	}

	self._csvSeed(filePath, csvColumns, transform, callback);
}

module.exports = new Postcode();
<commit_msg>Fixed location population for update script<commit_after>var	fs = require("fs"),
		S = require("string"),
		util = require("util"),
		path = require("path"),
		Pc = require("postcode"),
		async = require("async"),
		OSPoint = require("ospoint"),
		Base = require("./index").Base;

var postcodeSchema = {
	"id": "SERIAL PRIMARY KEY",
	"postcode" : "VARCHAR(10)",
	"pc_compact" : "VARCHAR(9)",
	"quality" : "INTEGER",
	"eastings" : "INTEGER",
	"northings" : "INTEGER",
	"country" : "VARCHAR(255)",
	"nhs_ha" : "VARCHAR(255)",
	"admin_county" : "VARCHAR(255)",
	"admin_district" : "VARCHAR(255)",
	"admin_ward" : "VARCHAR(255)",
	"longitude" : "DOUBLE PRECISION",
	"latitude" : "DOUBLE PRECISION",
	"location" : "GEOGRAPHY(Point, 4326)",
	"parliamentary_constituency" : "VARCHAR(255)",
	"european_electoral_region" : "VARCHAR(255)",
	"primary_care_trust" : "VARCHAR(255)",
	"region" : "VARCHAR(255)",
	"parish" : "VARCHAR(255)",
	"lsoa" : "VARCHAR(255)",
	"msoa" : "VARCHAR(255)",
	"nuts" : "VARCHAR(255)",
	"incode" : "VARCHAR(5)",
	"outcode" : "VARCHAR(5)",
	"ccg" : "VARCHAR(255)"
};

var indexes = [{
	unique: true,
	column: "postcode"
}, {
	unique: true,
	column: "pc_compact",
	opClass: "varchar_pattern_ops"
}, {
	type: "GIST",
	column: "location"
}, {
	column: "outcode"
}];

function Postcode () {
	Base.call(this, "postcodes", postcodeSchema, indexes);
}

util.inherits(Postcode, Base);

Postcode.prototype.find = function (postcode, callback) {
	if (typeof postcode !== "string") {
		return callback(null, null);
	}

	postcode = postcode.trim().toUpperCase();

	if (!new Pc(postcode).valid()) {
		return callback(null, null);
	}

	var query = "SELECT * FROM " + this.relation + " WHERE pc_compact=$1";

	this._query(query, [postcode.replace(" ", "")], function(error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		callback(null, result.rows[0]);
	});
}

Postcode.prototype.random = function (callback) {
	var query	=	"SELECT * FROM  ("+
					    "SELECT 1 + floor(random() * (SELECT count(id) FROM postcodes))::integer AS id "+
					    "FROM   generate_series(1, 100) g "+
					    "GROUP BY 1 "+
					    ") r "+
							"JOIN postcodes USING (id) "+
							"LIMIT  1;"

	this._query(query, function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		callback(null, result.rows[0]);
	});
}

Postcode.prototype.populateLocation = function (callback) {
	var query = "UPDATE postcodes SET location=ST_GeogFromText" +
							"('SRID=4326;POINT(' || longitude || ' ' || latitude || ')')" +
							" WHERE northings!=0 AND EASTINGS!=0";
	this._query(query, callback);
}

Postcode.prototype.search = function (postcode, options, callback) {
	var limit;
	if (typeof options === 'function') {
		callback = options;
		limit = 10;
	} else {
		limit = parseInt(options.limit, 10);
		if (isNaN(limit)) limit = 10;
		if (limit > 100) limit = 100;
	}

	var	query = "SELECT * FROM " + this.relation  + " WHERE pc_compact ~ $1 LIMIT $2",
			re = "^" + postcode.toUpperCase().replace(" ", "") + ".*";

	this._query(query, [re, limit], function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		return callback(null, result.rows);
	});
}

Postcode.prototype.nearestPostcodes = function (params, callback) {
	var radius = parseFloat(params.radius) || 100;
	if (radius > 1000) radius = 1000;

	var limit = parseInt(params.limit, 10) || 10;
	if (limit > 100) limit = 100;

	var longitude = parseFloat(params.longitude);
	if (isNaN(longitude)) return callback(new Error("Invalid longitude"), null);

	var latitude = parseFloat(params.latitude);
	if (isNaN(latitude)) return callback(new Error("Invalid latitude"), null);

	var query = "SELECT *, ST_Distance(location, " +
							" ST_GeographyFromText('POINT(' || $1 || ' ' || $2 || ')')) AS distance " +
							"FROM postcodes " +
							"WHERE ST_DWithin(location, ST_GeographyFromText('POINT(' || $1 || ' ' || $2 || ')'), $3) " +
							"ORDER BY distance LIMIT $4";
	this._query(query, [longitude, latitude, radius, limit], function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length === 0) {
			return callback(null, null);
		}
		return callback(null, result.rows);
	});
}

Postcode.prototype.findOutcode = function (outcode, callback) {
	outcode = outcode.trim().toUpperCase();

	if (!Pc.validOutcode(outcode)) {
		return callback(null, null);
	}

	var query = "Select avg(northings) as northings, avg(eastings) as eastings, " +
							"avg(ST_X(location::geometry)) as longitude, avg(ST_Y(location::geometry))" +
							" as latitude FROM postcodes WHERE postcodes.outcode=$1";

	this._query(query, [outcode], function (error, result) {
		if (error) return callback(error, null);
		if (result.rows.length !== 1) return callback(null, null);
		var outcodeResult = result.rows[0];
		if (!outcodeResult.eastings || !outcodeResult.northings) {
			return callback(null, null);
		}
		outcodeResult.outcode = outcode;
		return callback(null, result.rows[0]);
	});
}

Postcode.prototype.toJson = function (address) {
	delete address.id;
	delete address.location;
	delete address.pc_compact;
	return address;
}

/*
*  	ONS CSV Data Reference
*
*		0 - Unit postcode (7char)
*		1 - Unit postcode (8char)
*		2 - Unit postcode (variable)											Y
*		3 - Date of intro
*		4 - Date of termination (null = live)
*		5 - County 																				Y
*		6 - District 																			Y
*		7 - Ward 																					Y
*		8 - Postcode user type (small/large)
*		9 - Easting 																			Y
*		10 - Northings 																		Y
*		11 - Positional quality indicator 								Y
*		12 - Strategic health authority (SHA) (nhs_ha) 		Y
*		13 - Pan SHA (nhs_regional)
*		14 - Country 																			Y
*		15 - Region (region code, GOR)										Y
*		16 - Standard statistical region (SSR)
*		17 - Westminster parliamentary constituency 			Y
*		18 - European Electoral Register									Y
*		19 - Local learning and skills council
*		20 - Travel to work area
*		21 - Primary care trust 													Y
*		22 - NUTS / LAU areas 														Y
*		23 - 1991 census ed
*		24 - 1991 census ed with census code
*		25 - ed positional quality indicator
*		26 - Previous SHA prior to 2006
*		27 - LEA
*		28 - Health Authority (old style)
*		29 - 1991 ward
*		30 - 1991 ward OGSS code
*		31 - 1998 ward
*		32 - 2005 statistical ward
*		33 - 2001 census output area
*		34 - census area statistics ward
*		35 - national park
*		36 - 2001 LSOA
*		37 - 2001 MSOA
*		38 - 2001 rural/urban indicator
*		39 - 2001 OAC
*		40 - Old PCT
*		41 - 2011 census output areas 									Y
*		42 - 2011 LSOA																	Y
*		43 - 2011 MSOA 																	Y
*		44 - Parish 																		Y
*		45 - Census workplace zone
*
*
*/

Postcode.prototype.seedPostcodes = function (filePath, callback) {
	var self = this;
	var csvColumns = 	"postcode, pc_compact, eastings, northings, longitude," +
										" latitude, country, nhs_ha," +
										" admin_county, admin_district, admin_ward, parish, quality," +
										" parliamentary_constituency , european_electoral_region, region, " +
										" primary_care_trust, lsoa, msoa, nuts, incode, outcode, ccg";
	var dataPath = path.join(__dirname, "../../data/");
	var countries = JSON.parse(fs.readFileSync(dataPath + "countries.json"));
	var nhsHa = JSON.parse(fs.readFileSync(dataPath + "nhsHa.json"));
	var counties = JSON.parse(fs.readFileSync(dataPath + "counties.json"));
	var districts = JSON.parse(fs.readFileSync(dataPath + "districts.json"));
	var wards = JSON.parse(fs.readFileSync(dataPath + "wards.json"));
	var parishes = JSON.parse(fs.readFileSync(dataPath + "parishes.json"));
	var constituencies = JSON.parse(fs.readFileSync(dataPath + "constituencies.json"));
	var european_registers = JSON.parse(fs.readFileSync(dataPath + "european_registers.json"));
	var regions = JSON.parse(fs.readFileSync(dataPath + "regions.json"));
	var pcts = JSON.parse(fs.readFileSync(dataPath + "pcts.json"));
	var lsoa = JSON.parse(fs.readFileSync(dataPath + "lsoa.json"));
	var msoa = JSON.parse(fs.readFileSync(dataPath + "msoa.json"));
	var nuts = JSON.parse(fs.readFileSync(dataPath + "nuts.json"));
	var ccg = JSON.parse(fs.readFileSync(dataPath + "ccg.json"));

	var transform = function (row, index) {
		// Skip row if terminated
		if (row[4].length !== 0) {
			return null;
		}

		var finalRow = [];

		finalRow.push(row[2]);  												// postcode
		finalRow.push(row[2].replace(/\s/g, ""));				// pc_compact
		finalRow.push(row[9]);													// Eastings
		finalRow.push(row[10]);													// Northings

		var location;
		if (row[9].length === 0 || row[10].length === 0) {
			location = {
				longitude: "",
				latitude: ""
			};
		} else if (row[14] === "N92000002") {
			location = new OSPoint("" + row[10] , "" + row[9]).toWGS84("irish_national_grid");
		} else {
			location = new OSPoint("" + row[10] , "" + row[9]).toWGS84();
		}

		finalRow.push(location.longitude);							// longitude
		finalRow.push(location.latitude);								// latitude
		finalRow.push(countries[row[14]]);							// Country
		finalRow.push(nhsHa[row[12]]);									// NHS Health Authority
		finalRow.push(counties[row[5]]);								// County
		finalRow.push(districts[row[6]]);								// District
		finalRow.push(wards[row[7]]);										// Ward
		finalRow.push(parishes[row[44]]);								// Parish
		finalRow.push(row[11]);													// Quality
		finalRow.push(constituencies[row[17]]);					// Westminster const.
		finalRow.push(european_registers[row[18]]);			// European electoral region
		finalRow.push(regions[row[15]]);								// Region
		finalRow.push(pcts[row[21]]);										// Primary Care Trusts
		finalRow.push(lsoa[row[42]]);										// 2011 LSOA
		finalRow.push(msoa[row[43]]);										// 2011 MSOA
		finalRow.push(nuts[row[22]]);										// NUTS
		finalRow.push(row[2].split(" ")[1]);						// Incode
		finalRow.push(row[2].split(" ")[0]);						// Outcode
		finalRow.push(ccg[lsoa[row[42]]]);							// Clinical Commissioning Group

		return finalRow;
	}

	self._csvSeed(filePath, csvColumns, transform, callback);
}

module.exports = new Postcode();
<|endoftext|>