<commit_before>  <script type="text/javascript">
    var w = 960;
    var h = 500;
    var proj = d3.geo.mercator();
    var path = d3.geo.path().projection(proj);
    var t = proj.translate(); // the projection's default translation
    var s = proj.scale() // the projection's default scale

    var map = d3.select("#vis").append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .call(d3.behavior.zoom().on("zoom", redraw));

    var axes = map.append("svg:g").attr("id", "axes");

    var xAxis = axes.append("svg:line")
        .attr("x1", t[0])
        .attr("y1", 0)
        .attr("x2", t[0])
        .attr("y2", h);

    var yAxis = axes.append("svg:line")
        .attr("x1", 0)
        .attr("y1", t[1])
        .attr("x2", w)
        .attr("y2", t[1]);

    var uk = map.append("svg:g").attr("id", "uk");

    d3.json("uk.json", function (json) {
      uk.selectAll("path")
          .data(json.features)
        .enter().append("svg:path")
          .attr("d", path);
    });

    function redraw() {
      // d3.event.translate (an array) stores the current translation from the parent SVG element
      // t (an array) stores the projection's default translation
      // we add the x and y vales in each array to determine the projection's new translation
      var tx = t[0] * d3.event.scale + d3.event.translate[0];
      var ty = t[1] * d3.event.scale + d3.event.translate[1];
      proj.translate([tx, ty]);

      // now we determine the projection's new scale, but there's a problem:
      // the map doesn't 'zoom onto the mouse point'
      proj.scale(s * d3.event.scale);

      // redraw the map
      uk.selectAll("path").attr("d", path);

      // redraw the x axis
      xAxis.attr("x1", tx).attr("x2", tx);

      // redraw the y axis
      yAxis.attr("y1", ty).attr("y2", ty);
    }
  </script>
<commit_msg>Remove unnessary use .js<commit_after><|endoftext|>


<commit_before>var express = require('express'),
    app = module.exports = express(),
    config = require('../../lib/config'),
    path = require('path'),
    fs = require('fs'),
    Bundles = require('../bundles');

require('string.prototype.endswith');

app.set('views', process.cwd());

app.get('/viewsetup.js', function(req, res) {
    // Do some entirely silly string operations to extract the bundle name from the referer and pass it to the API setup script
    var referer = req.headers.referer;
    var start = referer.indexOf('/view/') + 6;
    var end = referer.indexOf('/', start + 1);
    var bundleName = referer.substring(start, end);

    res.type('.js');
    res.render('lib/includes/viewsetup.js.ejs', {host: config.host, port: config.port, bundleName: bundleName});
});

app.get('/view/:bundle_name*', function(req, res) {
    var bundleName = req.param('bundle_name');

    Bundles.find(bundleName)
        .then(function(bundle) {
            // We start out assuming the user is trying to reach the index page
            var resName = 'index.html';

            /*  We need a trailing slash for view index pages so that relatively linked assets can be reached as expected.
             This behaves a bit weird in that it adds two trailing slashes, this appears to be because both '' and '/'
             don't count as params. Luckily, the fact that we end up with '//' doesn't cause any problems. */
            if (!req.params[0] && !req.url.endsWith('/')) {
                res.redirect(req.url + '/');
            }

            // If the first param isn't just a slash, the user must be trying to resolve an asset and not the index page
            if (req.params[0] !== '/' && req.params[0] !== '//') {
                resName = req.params[0].substr(1);
            }

            var fileLocation = path.join(__dirname, '../../', bundle.dir, 'view/', resName);

            // Check if the file exists
            if (!fs.existsSync(fileLocation)) {
                res.status(404).send('Unable to find '+ bundle.dir +'/'+ resName);
            }

            res.sendFile(fileLocation);
        }, function (err) {
            res.status(404).send('Unable to find bundle \''+ bundleName +'\'');
        });
});

<commit_msg>I'm dumb sometimes. Fix last commit not loading views on Windows<commit_after>var express = require('express'),
    app = module.exports = express(),
    config = require('../../lib/config'),
    path = require('path'),
    fs = require('fs'),
    Bundles = require('../bundles');

require('string.prototype.endswith');

app.set('views', process.cwd());

app.get('/viewsetup.js', function(req, res) {
    // Do some entirely silly string operations to extract the bundle name from the referer and pass it to the API setup script
    var referer = req.headers.referer;
    var start = referer.indexOf('/view/') + 6;
    var end = referer.indexOf('/', start + 1);
    var bundleName = referer.substring(start, end);

    res.type('.js');
    res.render('lib/includes/viewsetup.js.ejs', {host: config.host, port: config.port, bundleName: bundleName});
});

app.get('/view/:bundle_name*', function(req, res) {
    var bundleName = req.param('bundle_name');

    Bundles.find(bundleName)
        .then(function(bundle) {
            // We start out assuming the user is trying to reach the index page
            var resName = 'index.html';

            /*  We need a trailing slash for view index pages so that relatively linked assets can be reached as expected.
             This behaves a bit weird in that it adds two trailing slashes, this appears to be because both '' and '/'
             don't count as params. Luckily, the fact that we end up with '//' doesn't cause any problems. */
            if (!req.params[0] && !req.url.endsWith('/')) {
                res.redirect(req.url + '/');
            }

            // If the first param isn't just a slash, the user must be trying to resolve an asset and not the index page
            if (req.params[0] !== '/' && !req.url.endsWith('/')) {
                resName = req.params[0].substr(1);
            }

            var fileLocation = path.join(__dirname, '../../', bundle.dir, 'view/', resName);

            // Check if the file exists
            if (!fs.existsSync(fileLocation)) {
                res.status(404).send('Unable to find '+ bundle.dir +'/'+ resName);
            }

            res.sendFile(fileLocation);
        }, function (err) {
            res.status(404).send('Unable to find bundle \''+ bundleName +'\'');
        });
});

<|endoftext|>


<commit_before>
module.exports = {
    w3cmemes: {
        origin:         "W3CMemes"
    ,   name:           "W3CMemes"
    ,   description:    "The official news agency for the W3C community"
    }
,   w3cnews: {
        origin:         "W3C News"
    ,   name:           "W3C News"
    ,   description:    "The party line"
    }
,   "html-wg":  {
        origin:         "github"
    ,   name:           "HTML WG"
    ,   description:    "HTML Working Group work stream"
    ,   repository:     [
                            "w3c/html"
                        ,   "w3c/charter-html"
                        ,   "w3c/test-results"
                        ,   "w3c/dom"
                        ,   "w3c/aria-in-html"
                        ]
    }
,   wpt:  {
        origin:         "github"
    ,   name:           "WPT"
    ,   description:    "Web Platform Tests work stream"
    ,   repository:     [
                            "w3c/web-platform-tests"
                        ,   "w3c/wpt-runner"
                        ,   "w3c/test-results"
                        ,   "w3c/wpt-tools"
                        ,   "w3c/testharness.js"
                        ]
    }
,   "modern-tooling":   {
        origin:         "github"
    ,   name:           "Modern Tooling"
    ,   description:    "Work stream for the Modern Tooling project"
    ,   repository:     [
                            "w3c/echidna"
                        ,   "w3c/modern-tooling"
                        ,   "w3c/pheme"
                        ,   "w3c/midgard"
                        ,   "w3c/ash-nazg"
                        ,   "w3c/specberus"
                        ,   "w3c/respec"
                        ,   "w3c/respec-docs"
                        ,   "w3c/w3c-api"
                        ,   "w3c/developers"
                        ,   "w3c/third-party-resources-checker"
                        ,   "w3c/tr-design"
                        ]
    }
,   "html-future":   {
        origin:         "github"
    ,   name:           "Future of HTML"
    ,   description:    "Discussion on the future of HTML"
    ,   repository:     [
                            "w3c/charter-html"
                        ]
    }
,   "webrtc":   {
        origin:         "github"
    ,   name:           "WebRTC specs"
    ,   description:    "Github activity on WebRTC specs"
    ,   repository:     [
                            "w3c/webrtc-pc"
                        ,   "w3c/webrtc-identity"
                        ,   "w3c/webrtc-quic"
                        ,   "w3c/webrtc-ice"
                        ,   "w3c/webrtc-priority"
                        ,   "w3c/webrtc-nv-use-cases"
                        ,   "w3c/mediacapture-main"
                        ,   "w3c/mediacapture-record"
                        ,   "w3c/mediacapture-image"
                        ,   "w3c/mediacapture-fromelement"
                        ,   "w3c/mediacapture-output"
                        ,   "w3c/webrtc-stats"
                        ,   "w3c/mediacapture-screen-share"
                        ,   "w3c/webrtc-charter"
                        ,   "w3c/webrtc-respec-ci"
                        ,   "w3c/mst-content-hint"
      ,   "w3c/webrtc-interop-reports"
      ,   "w3c/webrtc-svc"
      ,   "w3c/webrtc-extensions"
      ,   "w3c/mediacapture-extensions"
      ,   "w3c/webrtc-provisional-stats",
      "w3c/webrtc-encoded-transform", "w3c/mediacapture-automation", "w3c/mediacapture-transform", "w3c/mediacapture-region", "w3c/mediacapture-handle", "w3c/mediacapture-viewport", "w3c/media-pipeline-arch"
    ]
    }
,   "csvw":   {
        origin:         "github"
    ,   name:           "CSVW Specs"
    ,   description:    "Github activity on the CSV on the Web specs"
    ,   repository:     [
                            "w3c/csvw"
                        ]
    }
,   "dpub":   {
        origin:         "github"
    ,   name:           "DPUB documents"
    ,   description:    "Github activity around digital publishing"
    ,   repository:     [
                            "w3c/dpub",
                            "w3c/dpub-accessibility",
                            "w3c/dpub-annotation",
                            "w3c/dpub-content-and-markup",
                            "w3c/dpub-metadata",
                            "w3c/dpub-stem",
                            "w3c/dpub-validation",
                            "w3c/dpub-pwp",
                            "w3c/dpub-pwp-loc",
                            "w3c/dpub-pwp-arch",
                            "w3c/dpub-pwp-ucr"
                        ]
    }
,   "publ": {
        origin:      "github"
    ,   name:        "Publishing Working Group documents"
    ,   description: "Github activities around the Publishing on the Web WG specs"
    ,   repository:  [
                         "w3c/publ-wg",
                         "w3c/wpub",
                         "w3c/pwpub",
                         "w3c/epub4",
                         "w3c/dpub-aria-2.0",
                         "w3c/publ-a11y"
                     ]
    }
,   "poe": {
        origin:      "github"
    ,   name:        "POE Working Group documents"
    ,   description: "Github activity around the Permissions and Obligations Expression Working Group"
    ,   repository:  [
                         "w3c/poe"
                     ]
    }
,   "annotation":   {
        origin:         "github"
    ,   name:           "Web Annotations specs"
    ,   description:    "Github activity on Web Annotation specs"
    ,   repository:     [
                            "w3c/web-annotation",
                            "w3c/findtext"
                        ]
    }
,   "das":   {
        origin:         "github"
    ,   name:           "Device & Sensors specs"
    ,   description:    "Github activity on Device & Sensors Working Group specs"
    ,   repository:     [
                            "w3c/sensors"
                        ,   "w3c/ambient-light"
                        ,   "w3c/proximity"
                        ,   "w3c/vibration"
                        ,   "w3c/battery"
                        ,   "w3c/wake-lock"
                        ,   "w3c/html-media-capture"
                        ,   "w3c/devicesensors-wg"
                        ,   "w3c/gyroscope"
                        ,   "w3c/accelerometer"
                        ]
    }
,   "immersiveweb":   {
        origin:         "github"
    ,   name:           "Immersive Web Repositories"
    ,   description:    "Github activity on Immersive Web CG & WG"
    ,   repository:     [
                            "immersive-web/webxr"
                        ,   "immersive-web/administrativia"
                        ,   "immersive-web/homepage"
                        ,   "immersive-web/spatial-favicons"
                        ,   "immersive-web/lighting-estimation"
                        ,   "immersive-web/proposals"
                        ,   "immersive-web/privacy-and-security"
                        ,   "immersive-web/geo-alignment"
                        ,   "immersive-web/hit-test"
                        ,   "immersive-web/anchors"
                        ,   "immersive-web/community-resources"
                        ]
    }
,   "machinelearning":   {
        origin:         "github"
    ,   name:           "Web Machine Learning Repositories"
    ,   description:    "Github activity on WebML WG"
    ,   repository:     [
                            "webmachinelearning/webnn"
                        ,   "webmachinelearning/model-loader"
                        ,   "webmachinelearning/meetings"
                        ,   "webmachinelearning/proposals"
                        ,   "webmachinelearning/webmachinelearning-ethics"
    ]
    }
,   "web-networks":   {
        origin:         "github"
    ,   name:           "Web & Networks IG Repositories"
    ,   description:    "Github activity on Web & Networks Interest Group"
  ,   repository:     [
    "w3c/edge-computing-web-exploration",
    "w3c/network-emulation",
    "w3c/web-networks"
  ]
}
  , "reffy": {
    origin: "github",
    name: "Reffy ecosystem",
    description: "Github activity on reffy et al",
    repository: ["w3c/reffy", "w3c/strudy", "w3c/browser-specs", "w3c/webref", "w3c/browser-statuses"]
  }
};
<commit_msg>Add media related entries and update Immersive Web repos<commit_after>
module.exports = {
    w3cmemes: {
        origin:         "W3CMemes"
    ,   name:           "W3CMemes"
    ,   description:    "The official news agency for the W3C community"
    }
,   w3cnews: {
        origin:         "W3C News"
    ,   name:           "W3C News"
    ,   description:    "The party line"
    }
,   "html-wg":  {
        origin:         "github"
    ,   name:           "HTML WG"
    ,   description:    "HTML Working Group work stream"
    ,   repository:     [
                            "w3c/html"
                        ,   "w3c/charter-html"
                        ,   "w3c/test-results"
                        ,   "w3c/dom"
                        ,   "w3c/aria-in-html"
                        ]
    }
,   wpt:  {
        origin:         "github"
    ,   name:           "WPT"
    ,   description:    "Web Platform Tests work stream"
    ,   repository:     [
                            "w3c/web-platform-tests"
                        ,   "w3c/wpt-runner"
                        ,   "w3c/test-results"
                        ,   "w3c/wpt-tools"
                        ,   "w3c/testharness.js"
                        ]
    }
,   "modern-tooling":   {
        origin:         "github"
    ,   name:           "Modern Tooling"
    ,   description:    "Work stream for the Modern Tooling project"
    ,   repository:     [
                            "w3c/echidna"
                        ,   "w3c/modern-tooling"
                        ,   "w3c/pheme"
                        ,   "w3c/midgard"
                        ,   "w3c/ash-nazg"
                        ,   "w3c/specberus"
                        ,   "w3c/respec"
                        ,   "w3c/respec-docs"
                        ,   "w3c/w3c-api"
                        ,   "w3c/developers"
                        ,   "w3c/third-party-resources-checker"
                        ,   "w3c/tr-design"
                        ]
    }
,   "html-future":   {
        origin:         "github"
    ,   name:           "Future of HTML"
    ,   description:    "Discussion on the future of HTML"
    ,   repository:     [
                            "w3c/charter-html"
                        ]
    }
,   "webrtc":   {
        origin:         "github"
    ,   name:           "WebRTC specs"
    ,   description:    "Github activity on WebRTC specs"
    ,   repository:     [
                            "w3c/webrtc-pc"
                        ,   "w3c/webrtc-identity"
                        ,   "w3c/webrtc-quic"
                        ,   "w3c/webrtc-ice"
                        ,   "w3c/webrtc-priority"
                        ,   "w3c/webrtc-nv-use-cases"
                        ,   "w3c/mediacapture-main"
                        ,   "w3c/mediacapture-record"
                        ,   "w3c/mediacapture-image"
                        ,   "w3c/mediacapture-fromelement"
                        ,   "w3c/mediacapture-output"
                        ,   "w3c/webrtc-stats"
                        ,   "w3c/mediacapture-screen-share"
                        ,   "w3c/webrtc-charter"
                        ,   "w3c/webrtc-respec-ci"
                        ,   "w3c/mst-content-hint"
      ,   "w3c/webrtc-interop-reports"
      ,   "w3c/webrtc-svc"
      ,   "w3c/webrtc-extensions"
      ,   "w3c/mediacapture-extensions"
      ,   "w3c/webrtc-provisional-stats",
      "w3c/webrtc-encoded-transform", "w3c/mediacapture-automation", "w3c/mediacapture-transform", "w3c/mediacapture-region", "w3c/mediacapture-handle", "w3c/mediacapture-viewport", "w3c/media-pipeline-arch"
    ]
    }
,   "csvw":   {
        origin:         "github"
    ,   name:           "CSVW Specs"
    ,   description:    "Github activity on the CSV on the Web specs"
    ,   repository:     [
                            "w3c/csvw"
                        ]
    }
,   "dpub":   {
        origin:         "github"
    ,   name:           "DPUB documents"
    ,   description:    "Github activity around digital publishing"
    ,   repository:     [
                            "w3c/dpub",
                            "w3c/dpub-accessibility",
                            "w3c/dpub-annotation",
                            "w3c/dpub-content-and-markup",
                            "w3c/dpub-metadata",
                            "w3c/dpub-stem",
                            "w3c/dpub-validation",
                            "w3c/dpub-pwp",
                            "w3c/dpub-pwp-loc",
                            "w3c/dpub-pwp-arch",
                            "w3c/dpub-pwp-ucr"
                        ]
    }
,   "publ": {
        origin:      "github"
    ,   name:        "Publishing Working Group documents"
    ,   description: "Github activities around the Publishing on the Web WG specs"
    ,   repository:  [
                         "w3c/publ-wg",
                         "w3c/wpub",
                         "w3c/pwpub",
                         "w3c/epub4",
                         "w3c/dpub-aria-2.0",
                         "w3c/publ-a11y"
                     ]
    }
,   "poe": {
        origin:      "github"
    ,   name:        "POE Working Group documents"
    ,   description: "Github activity around the Permissions and Obligations Expression Working Group"
    ,   repository:  [
                         "w3c/poe"
                     ]
    }
,   "annotation":   {
        origin:         "github"
    ,   name:           "Web Annotations specs"
    ,   description:    "Github activity on Web Annotation specs"
    ,   repository:     [
                            "w3c/web-annotation",
                            "w3c/findtext"
                        ]
    }
,   "das":   {
        origin:         "github"
    ,   name:           "Device & Sensors specs"
    ,   description:    "Github activity on Device & Sensors Working Group specs"
    ,   repository:     [
                            "w3c/sensors"
                        ,   "w3c/ambient-light"
                        ,   "w3c/proximity"
                        ,   "w3c/vibration"
                        ,   "w3c/battery"
                        ,   "w3c/wake-lock"
                        ,   "w3c/html-media-capture"
                        ,   "w3c/devicesensors-wg"
                        ,   "w3c/gyroscope"
                        ,   "w3c/accelerometer"
                        ]
    }
,   "immersiveweb":   {
        origin:         "github"
    ,   name:           "Immersive Web Repositories"
    ,   description:    "Github activity on Immersive Web CG & WG"
    ,   repository:     [
                            "immersive-web/webxr"
                        ,   "immersive-web/webxr-gamepads-module"
                        ,   "immersive-web/webxr-ar-module"
                        ,   "immersive-web/hit-test"
                        ,   "immersive-web/dom-overlays"
                        ,   "immersive-web/layers"
                        ,   "immersive-web/anchors"
                        ,   "immersive-web/lighting-estimation"
                        ,   "immersive-web/webxr-hand-input"

                        ,   "immersive-web/webxr-samples"
                        ,   "immersive-web/proposals"

                        ,   "immersive-web/navigation"
                        ,   "immersive-web/computer-vision"
                        ,   "immersive-web/geo-alignment"
                        ,   "immersive-web/real-world-geometry"
                        ,   "immersive-web/spatial-favicons"
                        ,   "immersive-web/performance-improvements"
                        ,   "immersive-web/marker-tracking"
                        ,   "immersive-web/capture"
                        ,   "immersive-web/depth-sensing"

                        ,   "immersive-web/homepage"
                        ,   "immersive-web/privacy-and-security"
                        ,   "immersive-web/administrativia"
                        ,   "immersive-web/community-resources",
                        ,   "immersive-web/immersive-web.github.io"
                        ]
    }
,   "machinelearning":   {
        origin:         "github"
    ,   name:           "Web Machine Learning Repositories"
    ,   description:    "Github activity on WebML WG"
    ,   repository:     [
                            "webmachinelearning/webnn"
                        ,   "webmachinelearning/model-loader"
                        ,   "webmachinelearning/meetings"
                        ,   "webmachinelearning/proposals"
                        ,   "webmachinelearning/webmachinelearning-ethics"
    ]
    }
,   "web-networks":   {
        origin:         "github"
    ,   name:           "Web & Networks IG Repositories"
    ,   description:    "Github activity on Web & Networks Interest Group"
  ,   repository:     [
    "w3c/edge-computing-web-exploration",
    "w3c/network-emulation",
    "w3c/web-networks"
  ]
}
  , "reffy": {
    origin: "github",
    name: "Reffy ecosystem",
    description: "Github activity on reffy et al",
    repository: ["w3c/reffy", "w3c/strudy", "w3c/browser-specs", "w3c/webref", "w3c/browser-statuses"]
  }
,   mediawg: {
        origin:         "github"
    ,   name:           "Media WG"
    ,   description:    "Specs from the Media WG"
    ,   repository:     [
                            "w3c/media-wg"
                        ,   "w3c/charter-media-wg"
                        ,   "w3c/autoplay"
                        ,   "w3c/encrypted-media"
                        ,   "w3c/media-capabilities"
                        ,   "w3c/media-playback-quality"
                        ,   "w3c/mediasession"
                        ,   "w3c/media-source"
                        ,   "w3c/picture-in-picture"
                        ,   "w3c/webcodecs"
                        ,   "w3c/mse-byte-stream-format-registry"
                        ,   "w3c/mse-byte-stream-format-mpeg-audio"
                        ,   "w3c/mse-byte-stream-format-webm"
                        ,   "w3c/mse-byte-stream-format-mp2t"
                        ,   "w3c/mse-byte-stream-format-isobmff"
                        ]
  }
,   secondscreen: {
        origin:         "github"
    ,   name:           "Second Screen WG/CG"
    ,   description:    "Specs from the Second Screen WG/CG"
    ,   repository:     [
                            "w3c/secondscreen-wg"
                        ,   "w3c/presentation-api"
                        ,   "w3c/remote-playback"
                        ,   "w3c/openscreenprotocol"
                        ,   "w3c/window-placement"
                        ,   "w3c/secondscreen-charter"
                        ,   "webscreens/cg-charter"
                        ,   "webscreens/webscreens.github.io"
                        ]
  }
,   gpuweb: {
        origin:         "github"
    ,   name:           "GPU for the Web WG/CG"
    ,   description:    "Specs from the GPU for the Web WG/CG"
    ,   repository:     [
                            "gpuweb/admin"
                        ,   "gpuweb/gpuweb"
                        ,   "gpuweb/cts"
                        ,   "w3c/gpuweb-wg"
                        ]
  }
,   "media-and-entertainment": {
        origin:         "github"
    ,   name:           "Media and Entertainment"
    ,   description:    "Discussions tracked by the Media and Entertainment IG"
    ,   repository:     [
                            "w3c/media-and-entertainment"
                        ,   "w3c/avmedia-formats-cg"
                        ,   "w3c/ColorWeb-CG"
                        ,   "w3c/webmediaapi"
                        ,   "w3c/webmediaguidelines"
                        ,   "w3c/me-media-integration-guidelines"
                        ,   "w3c/me-media-timed-events"
                        ,   "w3c/me-cloud-browser",
                        ,   "w3c/me-vision"
                        ,   "webtiming/timingobject"
  }
};
<|endoftext|>


<commit_before>"use strict";

const $ = require("jquery");
const fuzzy = require("fuzzy");
const Mousetrap = require("mousetrap");
const {Textcomplete, Textarea} = require("textcomplete");
const emojiMap = require("./libs/simplemap.json");
const options = require("./options");
const constants = require("./constants");

const input = $("#input");
let textcomplete;

module.exports = {
	enable: enableAutocomplete,
	disable: () => {
		input.off("input.tabcomplete");
		Mousetrap(input.get(0)).off("tab", "keydown");

		if (textcomplete) {
			textcomplete.destroy();
			textcomplete = null;
		}
	},
};

const chat = $("#chat");
const sidebar = $("#sidebar");
const emojiSearchTerms = Object.keys(emojiMap);
const emojiStrategy = {
	id: "emoji",
	match: /\B:([-+\w:?]{2,}):?$/,
	search(term, callback) {
		// Trim colon from the matched term,
		// as we are unable to get a clean string from match regex
		term = term.replace(/:$/, ""),
		callback(fuzzyGrep(term, emojiSearchTerms));
	},
	template([string, original]) {
		return `<span class="emoji">${emojiMap[original]}</span> ${string}`;
	},
	replace([, original]) {
		return emojiMap[original];
	},
	index: 1,
};

const nicksStrategy = {
	id: "nicks",
	match: /\B(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/,
	search(term, callback) {
		term = term.slice(1);

		if (term[0] === "@") {
			callback(completeNicks(term.slice(1), true)
				.map((val) => ["@" + val[0], "@" + val[1]]));
		} else {
			callback(completeNicks(term, true));
		}
	},
	template([string]) {
		return string;
	},
	replace([, original], position = 1) {
		// If no postfix specified, return autocompleted nick as-is
		if (!options.nickPostfix) {
			return original;
		}

		// If there is whitespace in the input already, append space to nick
		if (position > 0 && /\s/.test(input.val())) {
			return original + " ";
		}

		// If nick is first in the input, append specified postfix
		return original + options.nickPostfix;
	},
	index: 1,
};

const chanStrategy = {
	id: "chans",
	match: /\B((#|\+|&|![A-Z0-9]{5})([^\x00\x0A\x0D\x20\x2C\x3A]+(:[^\x00\x0A\x0D\x20\x2C\x3A]*)?)?)$/,
	search(term, callback, match) {
		callback(completeChans(match[0]));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const commandStrategy = {
	id: "commands",
	match: /^\/(\w*)$/,
	search(term, callback) {
		callback(completeCommands("/" + term));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const foregroundColorStrategy = {
	id: "foreground-colors",
	match: /\x03(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback) {
		term = term.toLowerCase();

		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((i) => {
				if (fuzzy.test(term, i[1])) {
					return [i[0], fuzzy.match(term, i[1], {
						pre: "",
						post: "",
					}).rendered];
				}

				return i;
			});

		callback(matchingColorCodes);
	},
	template(value) {
		return `<span class="irc-fg${parseInt(value[0], 10)}">${value[1]}</span>`;
	},
	replace(value) {
		return "\x03" + value[0];
	},
	index: 1,
};

const backgroundColorStrategy = {
	id: "background-colors",
	match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback, match) {
		term = term.toLowerCase();
		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((pair) => {
				if (fuzzy.test(term, pair[1])) {
					return [pair[0], fuzzy.match(term, pair[1], {
						pre: "",
						post: "",
					}).rendered];
				}

				return pair;
			})
			.map((pair) => pair.concat(match[1])); // Needed to pass fg color to `template`...

		callback(matchingColorCodes);
	},
	template(value) {
		return `<span class="irc-fg${parseInt(value[2], 10)} irc-bg irc-bg${parseInt(value[0], 10)}">${value[1]}</span>`;
	},
	replace(value) {
		return "\x03$1," + value[0];
	},
	index: 2,
};

function enableAutocomplete() {
	let tabCount = 0;
	let lastMatch = "";
	let currentMatches = [];

	input.on("input.tabcomplete", () => {
		tabCount = 0;
		currentMatches = [];
		lastMatch = "";
	});

	Mousetrap(input.get(0)).bind("tab", (e) => {
		if (input.data("autocompleting")) {
			return;
		}

		e.preventDefault();

		const text = input.val();

		if (input.get(0).selectionStart !== text.length) {
			return;
		}

		if (tabCount === 0) {
			lastMatch = text.split(/\s/).pop();

			if (lastMatch.length === 0) {
				return;
			}

			currentMatches = completeNicks(lastMatch, false);

			if (currentMatches.length === 0) {
				return;
			}
		}

		const position = input.get(0).selectionStart - lastMatch.length;
		const newMatch = nicksStrategy.replace([0, currentMatches[tabCount % currentMatches.length]], position);

		input.val(text.substr(0, position) + newMatch);

		lastMatch = newMatch;
		tabCount++;
	}, "keydown");

	const editor = new Textarea(input.get(0));
	textcomplete = new Textcomplete(editor, {
		dropdown: {
			className: "textcomplete-menu",
			placement: "top",
		},
	});

	textcomplete.register([
		emojiStrategy,
		nicksStrategy,
		chanStrategy,
		commandStrategy,
		foregroundColorStrategy,
		backgroundColorStrategy,
	]);

	// Activate the first item by default
	// https://github.com/yuku-t/textcomplete/issues/93
	textcomplete.on("rendered", () => {
		if (textcomplete.dropdown.items.length > 0) {
			textcomplete.dropdown.items[0].activate();
		}
	});

	textcomplete.on("show", () => {
		input.data("autocompleting", true);
	});

	textcomplete.on("hidden", () => {
		input.data("autocompleting", false);
	});
}

function fuzzyGrep(term, array) {
	const results = fuzzy.filter(
		term,
		array,
		{
			pre: "",
			post: "",
		}
	);
	return results.map((el) => [el.string, el.original]);
}

function completeNicks(word, isFuzzy) {
	const users = chat.find(".active .users");
	word = word.toLowerCase();

	// Lobbies and private chats do not have an user list
	if (!users.length) {
		return [];
	}

	const words = users.data("nicks");

	if (isFuzzy) {
		return fuzzyGrep(word, words);
	}

	return $.grep(
		words,
		(w) => !w.toLowerCase().indexOf(word)
	);
}

function completeCommands(word) {
	const words = constants.commands.slice();

	return fuzzyGrep(word, words);
}

function completeChans(word) {
	const words = [];

	sidebar.find(".chan.active")
		.parent()
		.find(".chan")
		.each(function() {
			const self = $(this);

			if (!self.hasClass("lobby")) {
				words.push(self.attr("aria-label"));
			}
		});

	return fuzzyGrep(word, words);
}
<commit_msg>add autocompleted names to private chats<commit_after>"use strict";

const $ = require("jquery");
const fuzzy = require("fuzzy");
const Mousetrap = require("mousetrap");
const {Textcomplete, Textarea} = require("textcomplete");
const emojiMap = require("./libs/simplemap.json");
const options = require("./options");
const constants = require("./constants");

const input = $("#input");
let textcomplete;

module.exports = {
	enable: enableAutocomplete,
	disable: () => {
		input.off("input.tabcomplete");
		Mousetrap(input.get(0)).off("tab", "keydown");

		if (textcomplete) {
			textcomplete.destroy();
			textcomplete = null;
		}
	},
};

const chat = $("#chat");
const sidebar = $("#sidebar");
const emojiSearchTerms = Object.keys(emojiMap);
const emojiStrategy = {
	id: "emoji",
	match: /\B:([-+\w:?]{2,}):?$/,
	search(term, callback) {
		// Trim colon from the matched term,
		// as we are unable to get a clean string from match regex
		term = term.replace(/:$/, ""),
		callback(fuzzyGrep(term, emojiSearchTerms));
	},
	template([string, original]) {
		return `<span class="emoji">${emojiMap[original]}</span> ${string}`;
	},
	replace([, original]) {
		return emojiMap[original];
	},
	index: 1,
};

const nicksStrategy = {
	id: "nicks",
	match: /\B(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/,
	search(term, callback) {
		term = term.slice(1);

		if (term[0] === "@") {
			callback(completeNicks(term.slice(1), true)
				.map((val) => ["@" + val[0], "@" + val[1]]));
		} else {
			callback(completeNicks(term, true));
		}
	},
	template([string]) {
		return string;
	},
	replace([, original], position = 1) {
		// If no postfix specified, return autocompleted nick as-is
		if (!options.nickPostfix) {
			return original;
		}

		// If there is whitespace in the input already, append space to nick
		if (position > 0 && /\s/.test(input.val())) {
			return original + " ";
		}

		// If nick is first in the input, append specified postfix
		return original + options.nickPostfix;
	},
	index: 1,
};

const chanStrategy = {
	id: "chans",
	match: /\B((#|\+|&|![A-Z0-9]{5})([^\x00\x0A\x0D\x20\x2C\x3A]+(:[^\x00\x0A\x0D\x20\x2C\x3A]*)?)?)$/,
	search(term, callback, match) {
		callback(completeChans(match[0]));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const commandStrategy = {
	id: "commands",
	match: /^\/(\w*)$/,
	search(term, callback) {
		callback(completeCommands("/" + term));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const foregroundColorStrategy = {
	id: "foreground-colors",
	match: /\x03(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback) {
		term = term.toLowerCase();

		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((i) => {
				if (fuzzy.test(term, i[1])) {
					return [i[0], fuzzy.match(term, i[1], {
						pre: "",
						post: "",
					}).rendered];
				}

				return i;
			});

		callback(matchingColorCodes);
	},
	template(value) {
		return `<span class="irc-fg${parseInt(value[0], 10)}">${value[1]}</span>`;
	},
	replace(value) {
		return "\x03" + value[0];
	},
	index: 1,
};

const backgroundColorStrategy = {
	id: "background-colors",
	match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback, match) {
		term = term.toLowerCase();
		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((pair) => {
				if (fuzzy.test(term, pair[1])) {
					return [pair[0], fuzzy.match(term, pair[1], {
						pre: "",
						post: "",
					}).rendered];
				}

				return pair;
			})
			.map((pair) => pair.concat(match[1])); // Needed to pass fg color to `template`...

		callback(matchingColorCodes);
	},
	template(value) {
		return `<span class="irc-fg${parseInt(value[2], 10)} irc-bg irc-bg${parseInt(value[0], 10)}">${value[1]}</span>`;
	},
	replace(value) {
		return "\x03$1," + value[0];
	},
	index: 2,
};

function enableAutocomplete() {
	let tabCount = 0;
	let lastMatch = "";
	let currentMatches = [];

	input.on("input.tabcomplete", () => {
		tabCount = 0;
		currentMatches = [];
		lastMatch = "";
	});

	Mousetrap(input.get(0)).bind("tab", (e) => {
		if (input.data("autocompleting")) {
			return;
		}

		e.preventDefault();

		const text = input.val();

		if (input.get(0).selectionStart !== text.length) {
			return;
		}

		if (tabCount === 0) {
			lastMatch = text.split(/\s/).pop();

			if (lastMatch.length === 0) {
				return;
			}

			currentMatches = completeNicks(lastMatch, false);

			if (currentMatches.length === 0) {
				return;
			}
		}

		const position = input.get(0).selectionStart - lastMatch.length;
		const newMatch = nicksStrategy.replace([0, currentMatches[tabCount % currentMatches.length]], position);

		input.val(text.substr(0, position) + newMatch);

		lastMatch = newMatch;
		tabCount++;
	}, "keydown");

	const editor = new Textarea(input.get(0));
	textcomplete = new Textcomplete(editor, {
		dropdown: {
			className: "textcomplete-menu",
			placement: "top",
		},
	});

	textcomplete.register([
		emojiStrategy,
		nicksStrategy,
		chanStrategy,
		commandStrategy,
		foregroundColorStrategy,
		backgroundColorStrategy,
	]);

	// Activate the first item by default
	// https://github.com/yuku-t/textcomplete/issues/93
	textcomplete.on("rendered", () => {
		if (textcomplete.dropdown.items.length > 0) {
			textcomplete.dropdown.items[0].activate();
		}
	});

	textcomplete.on("show", () => {
		input.data("autocompleting", true);
	});

	textcomplete.on("hidden", () => {
		input.data("autocompleting", false);
	});
}

function fuzzyGrep(term, array) {
	const results = fuzzy.filter(
		term,
		array,
		{
			pre: "",
			post: "",
		}
	);
	return results.map((el) => [el.string, el.original]);
}

function rawNicks() {
	const chan = chat.find(".active");
	const users = chan.find(".users");

	// If this channel has a list of nicks, just return it
	if (users.length > 0) {
		return users.data("nicks");
	}

	const me = $("#nick-value").text();
	const otherUser = chan.attr("aria-label");

	// If this is a query, add their name to autocomplete
	if (me !== otherUser && chan.data("type") === "query") {
		return [otherUser, me];
	}

	// Return our own name by default for anything that isn't a channel or query
	return [me];
}

function completeNicks(word, isFuzzy) {
	const users = rawNicks();
	word = word.toLowerCase();

	if (isFuzzy) {
		return fuzzyGrep(word, users);
	}

	return $.grep(
		users,
		(w) => !w.toLowerCase().indexOf(word)
	);
}

function completeCommands(word) {
	const words = constants.commands.slice();

	return fuzzyGrep(word, words);
}

function completeChans(word) {
	const words = [];

	sidebar.find(".chan.active")
		.parent()
		.find(".chan")
		.each(function() {
			const self = $(this);

			if (!self.hasClass("lobby")) {
				words.push(self.attr("aria-label"));
			}
		});

	return fuzzyGrep(word, words);
}
<|endoftext|>


<commit_before>import { relativeUri, getId } from './uriParser'
import Constants from '../constants/Constants'

export function processSearchResponse (response, locationQuery) {
  const processedResponse = {}
  if (response.error) {
    processedResponse.error = response.error
  } else {
    const filteredLanguages = []
    processedResponse.filters = processAggregationsToFilters(response, locationQuery, filteredLanguages)
    const searchResults = response.aggregations.byWork.buckets.map(element => {
      const result = {}

      result.workUri = element.key
      result.id = getId(result.workUri)
      result.relativeUri = relativeUri(result.workUri)
      result.publication = element.publications.hits.hits[ 0 ]._source
      result.publication.contributors = result.publication.contributors || []
      result.publication.contributors = result.publication.contributors.filter(contributor => {
        return contributor.mainEntry
      })
      result.publication.contributors.forEach(contributor => {
        contributor.agent.relativeUri = relativeUri(contributor.agent.uri)
      })

      let selected // will be our selected publication for display, based on language criteria

      // If there is an active language filter, choose a publication that matches language
      // according to the preferred list.
      if (filteredLanguages.length > 0) {
        for (let i = 0; i < Constants.preferredLanguages.lengh; i++) {
          const prefLang = Constants.preferredLanguages[i]
          for (let j = 0; j < filteredLanguages; j++) {
            const filterLang = filteredLanguages[j]
            if (prefLang === filterLang && result.publication.langTitles[prefLang]) {
              // There might be several publications in the same language. We choose the first.
              selected = result.publication.langTitles[prefLang][0]
              break
            }
          }
          if (selected) {
            break
          }
        }
      }

      if (!selected) {
        // If the search query has match in the publication which elasticsearch returns as best match, use that.
        const titles = `${result.publication.mainTitle} ${result.publication.subtitle} ${result.publication.partNumber} ${result.publication.partTitle}`
        if (titles.toLocaleLowerCase().includes(locationQuery.query.toLocaleLowerCase())) {
          selected = result.publication
        }
      }

      if (!selected) {
        // We still haven't selected a publication, choose one among the available,
        // according to the list of preferred languages.
        for (let i = 0; i < Constants.preferredLanguages.lengh; i++) {
          const prefLang = Constants.preferredLanguages[i]
          if (result.publication.langTitles[prefLang]) {
            // There might be several publications in the same language. We choose the first.
            selected = result.publication.langTitles[prefLang][0]
            break
          }
        }
      }

      if (!selected) {
        // Still no match, use the publication which elasticsearch returns as best match
        selected = result.publication
      }

      if (selected.subtitle) {
        result.titleLine1 = `${selected.mainTitle} : ${selected.subtitle}`
      } else {
        result.titleLine1 = selected.mainTitle
      }
      if (selected.partNumber && selected.partTitle) {
        result.titleLine2 = `${selected.partNumber}. ${selected.partTitle}`
      } else if (selected.partNumber) {
        result.titleLine2 = selected.partNumber
      } else if (selected.partTitle) {
        result.titleLine2 = selected.partTitle
      } else {
        result.titleLine2 = ''
      }

      if (selected.pubUri) {
        result.relativePublicationUri = `${result.relativeUri}${relativeUri(selected.pubUri)}`
      } else {
        result.relativePublicationUri = `${result.relativeUri}${relativeUri(result.publication.uri)}`
      }

      result.mediaTypes = result.publication.mediaTypesFromAllPublications || []
      result.image = selected.image
      if (!result.image) {
        // Choose any available based on preferred languages
        for (let i = 0; i < Constants.preferredLanguages.lengh; i++) {
          const prefLang = Constants.preferredLanguages[i]
          if (result.publication.langTitles[prefLang] && result.publication.langTitles[prefLang].image) {
            result.image = result.publication.langTitles[prefLang].image
            break
          }
        }
      }

      return result
    })
    processedResponse.searchResults = searchResults
    processedResponse.totalHits = response.aggregations.workCount.value
    processedResponse.totalHitsPublications = response.hits.total
  }
  return processedResponse
}

export function processAggregationsToFilters (response, locationQuery, filteredLanguages) {
  const filters = []
  const filterParameters = locationQuery[ 'filter' ] instanceof Array ? locationQuery[ 'filter' ] : [ locationQuery[ 'filter' ] ]

  const facets = response.aggregations.facets
  Object.keys(Constants.filterableFields).forEach(fieldShortName => {
    const field = Constants.filterableFields[ fieldShortName ]
    const fieldName = field.name
    const aggregation = facets[ fieldName ][ fieldName ]
    if (aggregation) {
      aggregation.buckets.forEach(bucket => {
        const filterId = `${fieldShortName}_${bucket.key.substring(field.prefix.length)}`
        const filterParameter = filterParameters.find(filterParameter => filterParameter === filterId)
        const active = filterParameter !== undefined
        if (active && filterId.startsWith('language')) {
          filteredLanguages.push(bucket.key)
        }
        filters.push({ id: filterId, bucket: bucket.key, count: bucket.doc_count, active: active })
      })
    }
  })

  return filters
}
<commit_msg>patron-client: fix for loops selecting language<commit_after>import { relativeUri, getId } from './uriParser'
import Constants from '../constants/Constants'

export function processSearchResponse (response, locationQuery) {
  const processedResponse = {}
  if (response.error) {
    processedResponse.error = response.error
  } else {
    const filteredLanguages = []
    processedResponse.filters = processAggregationsToFilters(response, locationQuery, filteredLanguages)
    const searchResults = response.aggregations.byWork.buckets.map(element => {
      const result = {}

      result.workUri = element.key
      result.id = getId(result.workUri)
      result.relativeUri = relativeUri(result.workUri)
      result.publication = element.publications.hits.hits[ 0 ]._source
      result.publication.contributors = result.publication.contributors || []
      result.publication.contributors = result.publication.contributors.filter(contributor => {
        return contributor.mainEntry
      })
      result.publication.contributors.forEach(contributor => {
        contributor.agent.relativeUri = relativeUri(contributor.agent.uri)
      })

      let selected // will be our selected publication for display, based on language criteria

      // If there is an active language filter, choose a publication that matches language
      // according to the preferred list.
      if (filteredLanguages.length > 0) {
        for (let prefLang of Constants.preferredLanguages) {
          for (let filterLang of filteredLanguages) {
            if (prefLang === filterLang && result.publication.langTitles[prefLang]) {
              // There might be several publications in the same language. We choose the first.
              selected = result.publication.langTitles[prefLang][0]
              break
            }
          }
          if (selected) {
            break
          }
        }
      }

      if (!selected) {
        // If the search query has match in the publication which elasticsearch returns as best match, use that.
        const titles = `${result.publication.mainTitle} ${result.publication.subtitle} ${result.publication.partNumber} ${result.publication.partTitle}`
        if (titles.toLocaleLowerCase().includes(locationQuery.query.toLocaleLowerCase())) {
          selected = result.publication
        }
      }

      if (!selected) {
        // We still haven't selected a publication, choose one among the available,
        // according to the list of preferred languages.
        for (let prefLang of Constants.preferredLanguages) {
          if (result.publication.langTitles[prefLang]) {
            // There might be several publications in the same language. We choose the first.
            selected = result.publication.langTitles[prefLang][0]
            break
          }
        }
      }

      if (!selected) {
        // Still no match, use the publication which elasticsearch returns as best match
        selected = result.publication
      }

      if (selected.subtitle) {
        result.titleLine1 = `${selected.mainTitle} : ${selected.subtitle}`
      } else {
        result.titleLine1 = selected.mainTitle
      }
      if (selected.partNumber && selected.partTitle) {
        result.titleLine2 = `${selected.partNumber}. ${selected.partTitle}`
      } else if (selected.partNumber) {
        result.titleLine2 = selected.partNumber
      } else if (selected.partTitle) {
        result.titleLine2 = selected.partTitle
      } else {
        result.titleLine2 = ''
      }

      if (selected.pubUri) {
        result.relativePublicationUri = `${result.relativeUri}${relativeUri(selected.pubUri)}`
      } else {
        result.relativePublicationUri = `${result.relativeUri}${relativeUri(result.publication.uri)}`
      }

      result.mediaTypes = result.publication.mediaTypesFromAllPublications || []
      result.image = selected.image
      if (!result.image) {
        // Choose any available based on preferred languages
        for (let i = 0; i < Constants.preferredLanguages.lengh; i++) {
          const prefLang = Constants.preferredLanguages[i]
          if (result.publication.langTitles[prefLang] && result.publication.langTitles[prefLang].image) {
            result.image = result.publication.langTitles[prefLang].image
            break
          }
        }
      }

      return result
    })
    processedResponse.searchResults = searchResults
    processedResponse.totalHits = response.aggregations.workCount.value
    processedResponse.totalHitsPublications = response.hits.total
  }
  return processedResponse
}

export function processAggregationsToFilters (response, locationQuery, filteredLanguages) {
  const filters = []
  const filterParameters = locationQuery[ 'filter' ] instanceof Array ? locationQuery[ 'filter' ] : [ locationQuery[ 'filter' ] ]

  const facets = response.aggregations.facets
  Object.keys(Constants.filterableFields).forEach(fieldShortName => {
    const field = Constants.filterableFields[ fieldShortName ]
    const fieldName = field.name
    const aggregation = facets[ fieldName ][ fieldName ]
    if (aggregation) {
      aggregation.buckets.forEach(bucket => {
        const filterId = `${fieldShortName}_${bucket.key.substring(field.prefix.length)}`
        const filterParameter = filterParameters.find(filterParameter => filterParameter === filterId)
        const active = filterParameter !== undefined
        if (active && filterId.startsWith('language')) {
          filteredLanguages.push(bucket.key)
        }
        filters.push({ id: filterId, bucket: bucket.key, count: bucket.doc_count, active: active })
      })
    }
  })

  return filters
}
<|endoftext|>


<commit_before>"use strict";

const constants = require("./constants");

import Mousetrap from "mousetrap";
import {Textcomplete, Textarea} from "textcomplete";
import fuzzy from "fuzzy";

import emojiMap from "./helpers/simplemap.json";
import store from "./store";

export default enableAutocomplete;

const emojiSearchTerms = Object.keys(emojiMap);
const emojiStrategy = {
	id: "emoji",
	match: /\B:([-+\w:?]{2,}):?$/,
	search(term, callback) {
		// Trim colon from the matched term,
		// as we are unable to get a clean string from match regex
		(term = term.replace(/:$/, "")), callback(fuzzyGrep(term, emojiSearchTerms));
	},
	template([string, original]) {
		return `<span class="emoji">${emojiMap[original]}</span> ${string}`;
	},
	replace([, original]) {
		return emojiMap[original];
	},
	index: 1,
};

const nicksStrategy = {
	id: "nicks",
	match: /\B(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/,
	search(term, callback) {
		term = term.slice(1);

		if (term[0] === "@") {
			callback(completeNicks(term.slice(1), true).map((val) => ["@" + val[0], "@" + val[1]]));
		} else {
			callback(completeNicks(term, true));
		}
	},
	template([string]) {
		return string;
	},
	replace([, original], position = 1) {
		// If no postfix specified, return autocompleted nick as-is
		if (!store.state.settings.nickPostfix) {
			return original;
		}

		// If there is whitespace in the input already, append space to nick
		if (position > 0 && /\s/.test(store.state.activeChannel.channel.pendingMessage)) {
			return original + " ";
		}

		// If nick is first in the input, append specified postfix
		return original + store.state.settings.nickPostfix;
	},
	index: 1,
};

const chanStrategy = {
	id: "chans",
	match: /\B((#|\+|&|![A-Z0-9]{5})([^\x00\x0A\x0D\x20\x2C\x3A]+(:[^\x00\x0A\x0D\x20\x2C\x3A]*)?)?)$/,
	search(term, callback, match) {
		callback(completeChans(match[0]));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const commandStrategy = {
	id: "commands",
	match: /^\/(\w*)$/,
	search(term, callback) {
		callback(completeCommands("/" + term));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const foregroundColorStrategy = {
	id: "foreground-colors",
	match: /\x03(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback) {
		term = term.toLowerCase();

		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((i) => {
				if (fuzzy.test(term, i[1])) {
					return [
						i[0],
						fuzzy.match(term, i[1], {
							pre: "",
							post: "",
						}).rendered,
					];
				}

				return i;
			});

		callback(matchingColorCodes);
	},
	template(value) {
		return `<span class="irc-fg${parseInt(value[0], 10)}">${value[1]}</span>`;
	},
	replace(value) {
		return "\x03" + value[0];
	},
	index: 1,
};

const backgroundColorStrategy = {
	id: "background-colors",
	match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback, match) {
		term = term.toLowerCase();
		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((pair) => {
				if (fuzzy.test(term, pair[1])) {
					return [
						pair[0],
						fuzzy.match(term, pair[1], {
							pre: "",
							post: "",
						}).rendered,
					];
				}

				return pair;
			})
			.map((pair) => pair.concat(match[1])); // Needed to pass fg color to `template`...

		callback(matchingColorCodes);
	},
	template(value) {
		return `${value[1]}`;
	},
	replace(value) {
		return "\x03$1," + value[0];
	},
	index: 2,
};

function enableAutocomplete(input) {
	let tabCount = 0;
	let lastMatch = "";
	let currentMatches = [];

	input.addEventListener("input", (e) => {
		if (e.detail === "autocomplete") {
			return;
		}

		tabCount = 0;
		currentMatches = [];
		lastMatch = "";
	});

	Mousetrap(input).bind(
		"tab",
		(e) => {
			if (store.state.isAutoCompleting) {
				return;
			}

			e.preventDefault();

			const text = input.value;

			if (tabCount === 0) {
				lastMatch = text
					.substring(0, input.selectionStart)
					.split(/\s/)
					.pop();

				if (lastMatch.length === 0) {
					return;
				}

				currentMatches = completeNicks(lastMatch, false);

				if (currentMatches.length === 0) {
					return;
				}
			}

			const position = input.selectionStart - lastMatch.length;
			const newMatch = nicksStrategy.replace(
				[0, currentMatches[tabCount % currentMatches.length]],
				position
			);
			const remainder = text.substr(input.selectionStart);

			input.value = text.substr(0, position) + newMatch + remainder;
			input.selectionStart -= remainder.length;
			input.selectionEnd = input.selectionStart;

			// Propagate change to Vue model
			input.dispatchEvent(
				new CustomEvent("input", {
					detail: "autocomplete",
				})
			);

			lastMatch = newMatch;
			tabCount++;
		},
		"keydown"
	);

	const editor = new Textarea(input);
	const textcomplete = new Textcomplete(editor, {
		dropdown: {
			className: "textcomplete-menu",
			placement: "top",
		},
	});

	textcomplete.register([
		emojiStrategy,
		nicksStrategy,
		chanStrategy,
		commandStrategy,
		foregroundColorStrategy,
		backgroundColorStrategy,
	]);

	// Activate the first item by default
	// https://github.com/yuku-t/textcomplete/issues/93
	textcomplete.on("rendered", () => {
		if (textcomplete.dropdown.items.length > 0) {
			textcomplete.dropdown.items[0].activate();
		}
	});

	textcomplete.on("show", () => {
		store.commit("isAutoCompleting", true);
	});

	textcomplete.on("hidden", () => {
		store.commit("isAutoCompleting", false);
	});

	return {
		hide() {
			textcomplete.hide();
		},
		destroy() {
			textcomplete.destroy();
			store.commit("isAutoCompleting", false);
		},
	};
}

function fuzzyGrep(term, array) {
	const results = fuzzy.filter(term, array, {
		pre: "",
		post: "",
	});
	return results.map((el) => [el.string, el.original]);
}

function rawNicks() {
	if (store.state.activeChannel.channel.users.length > 0) {
		const users = store.state.activeChannel.channel.users.slice();

		return users.sort((a, b) => b.lastMessage - a.lastMessage).map((u) => u.nick);
	}

	const me = store.state.activeChannel.network.nick;
	const otherUser = store.state.activeChannel.channel.name;

	// If this is a query, add their name to autocomplete
	if (me !== otherUser && store.state.activeChannel.channel.type === "query") {
		return [otherUser, me];
	}

	// Return our own name by default for anything that isn't a channel or query
	return [me];
}

function completeNicks(word, isFuzzy) {
	const users = rawNicks();
	word = word.toLowerCase();

	if (isFuzzy) {
		return fuzzyGrep(word, users);
	}

	return users.filter((w) => !w.toLowerCase().indexOf(word));
}

function completeCommands(word) {
	const words = constants.commands.slice();

	return fuzzyGrep(word, words);
}

function completeChans(word) {
	const words = [];

	for (const channel of store.state.activeChannel.network.channels) {
		if (channel.type === "channel") {
			words.push(channel.name);
		}
	}

	return fuzzyGrep(word, words);
}
<commit_msg>Trigger autocompletion only after whitespace<commit_after>"use strict";

const constants = require("./constants");

import Mousetrap from "mousetrap";
import {Textcomplete, Textarea} from "textcomplete";
import fuzzy from "fuzzy";

import emojiMap from "./helpers/simplemap.json";
import store from "./store";

export default enableAutocomplete;

const emojiSearchTerms = Object.keys(emojiMap);
const emojiStrategy = {
	id: "emoji",
	match: /(^|\s):([-+\w:?]{2,}):?$/,
	search(term, callback) {
		// Trim colon from the matched term,
		// as we are unable to get a clean string from match regex
		term = term.replace(/:$/, "");
		callback(fuzzyGrep(term, emojiSearchTerms));
	},
	template([string, original]) {
		return `<span class="emoji">${emojiMap[original]}</span> ${string}`;
	},
	replace([, original]) {
		return "$1" + emojiMap[original];
	},
	index: 2,
};

const nicksStrategy = {
	id: "nicks",
	match: /(^|\s)(@([a-zA-Z_[\]\\^{}|`@][a-zA-Z0-9_[\]\\^{}|`-]*)?)$/,
	search(term, callback) {
		term = term.slice(1);

		if (term[0] === "@") {
			callback(completeNicks(term.slice(1), true).map((val) => ["@" + val[0], "@" + val[1]]));
		} else {
			callback(completeNicks(term, true));
		}
	},
	template([string]) {
		return string;
	},
	replace([, original], position = 1) {
		// If no postfix specified, return autocompleted nick as-is
		if (!store.state.settings.nickPostfix) {
			return "$1" + original;
		}

		// If there is whitespace in the input already, append space to nick
		if (position > 0 && /\s/.test(store.state.activeChannel.channel.pendingMessage)) {
			return "$1" + original + " ";
		}

		// If nick is first in the input, append specified postfix
		return "$1" + original + store.state.settings.nickPostfix;
	},
	index: 2,
};

const chanStrategy = {
	id: "chans",
	match: /(^|\s)((?:#|\+|&|![A-Z0-9]{5})(?:[^\s]+)?)$/,
	search(term, callback) {
		callback(completeChans(term));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return "$1" + original;
	},
	index: 2,
};

const commandStrategy = {
	id: "commands",
	match: /^\/(\w*)$/,
	search(term, callback) {
		callback(completeCommands("/" + term));
	},
	template([string]) {
		return string;
	},
	replace([, original]) {
		return original;
	},
	index: 1,
};

const foregroundColorStrategy = {
	id: "foreground-colors",
	match: /\x03(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback) {
		term = term.toLowerCase();

		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((i) => {
				if (fuzzy.test(term, i[1])) {
					return [
						i[0],
						fuzzy.match(term, i[1], {
							pre: "",
							post: "",
						}).rendered,
					];
				}

				return i;
			});

		callback(matchingColorCodes);
	},
	template(value) {
		return `<span class="irc-fg${parseInt(value[0], 10)}">${value[1]}</span>`;
	},
	replace(value) {
		return "\x03" + value[0];
	},
	index: 1,
};

const backgroundColorStrategy = {
	id: "background-colors",
	match: /\x03(\d{2}),(\d{0,2}|[A-Za-z ]{0,10})$/,
	search(term, callback, match) {
		term = term.toLowerCase();
		const matchingColorCodes = constants.colorCodeMap
			.filter((i) => fuzzy.test(term, i[0]) || fuzzy.test(term, i[1]))
			.map((pair) => {
				if (fuzzy.test(term, pair[1])) {
					return [
						pair[0],
						fuzzy.match(term, pair[1], {
							pre: "",
							post: "",
						}).rendered,
					];
				}

				return pair;
			})
			.map((pair) => pair.concat(match[1])); // Needed to pass fg color to `template`...

		callback(matchingColorCodes);
	},
	template(value) {
		return `${value[1]}`;
	},
	replace(value) {
		return "\x03$1," + value[0];
	},
	index: 2,
};

function enableAutocomplete(input) {
	let tabCount = 0;
	let lastMatch = "";
	let currentMatches = [];

	input.addEventListener("input", (e) => {
		if (e.detail === "autocomplete") {
			return;
		}

		tabCount = 0;
		currentMatches = [];
		lastMatch = "";
	});

	Mousetrap(input).bind(
		"tab",
		(e) => {
			if (store.state.isAutoCompleting) {
				return;
			}

			e.preventDefault();

			const text = input.value;

			if (tabCount === 0) {
				lastMatch = text
					.substring(0, input.selectionStart)
					.split(/\s/)
					.pop();

				if (lastMatch.length === 0) {
					return;
				}

				currentMatches = completeNicks(lastMatch, false);

				if (currentMatches.length === 0) {
					return;
				}
			}

			const position = input.selectionStart - lastMatch.length;
			const newMatch = nicksStrategy.replace(
				[0, currentMatches[tabCount % currentMatches.length]],
				position
			);
			const remainder = text.substr(input.selectionStart);

			input.value = text.substr(0, position) + newMatch + remainder;
			input.selectionStart -= remainder.length;
			input.selectionEnd = input.selectionStart;

			// Propagate change to Vue model
			input.dispatchEvent(
				new CustomEvent("input", {
					detail: "autocomplete",
				})
			);

			lastMatch = newMatch;
			tabCount++;
		},
		"keydown"
	);

	const editor = new Textarea(input);
	const textcomplete = new Textcomplete(editor, {
		dropdown: {
			className: "textcomplete-menu",
			placement: "top",
		},
	});

	textcomplete.register([
		emojiStrategy,
		nicksStrategy,
		chanStrategy,
		commandStrategy,
		foregroundColorStrategy,
		backgroundColorStrategy,
	]);

	// Activate the first item by default
	// https://github.com/yuku-t/textcomplete/issues/93
	textcomplete.on("rendered", () => {
		if (textcomplete.dropdown.items.length > 0) {
			textcomplete.dropdown.items[0].activate();
		}
	});

	textcomplete.on("show", () => {
		store.commit("isAutoCompleting", true);
	});

	textcomplete.on("hidden", () => {
		store.commit("isAutoCompleting", false);
	});

	return {
		hide() {
			textcomplete.hide();
		},
		destroy() {
			textcomplete.destroy();
			store.commit("isAutoCompleting", false);
		},
	};
}

function fuzzyGrep(term, array) {
	const results = fuzzy.filter(term, array, {
		pre: "",
		post: "",
	});
	return results.map((el) => [el.string, el.original]);
}

function rawNicks() {
	if (store.state.activeChannel.channel.users.length > 0) {
		const users = store.state.activeChannel.channel.users.slice();

		return users.sort((a, b) => b.lastMessage - a.lastMessage).map((u) => u.nick);
	}

	const me = store.state.activeChannel.network.nick;
	const otherUser = store.state.activeChannel.channel.name;

	// If this is a query, add their name to autocomplete
	if (me !== otherUser && store.state.activeChannel.channel.type === "query") {
		return [otherUser, me];
	}

	// Return our own name by default for anything that isn't a channel or query
	return [me];
}

function completeNicks(word, isFuzzy) {
	const users = rawNicks();
	word = word.toLowerCase();

	if (isFuzzy) {
		return fuzzyGrep(word, users);
	}

	return users.filter((w) => !w.toLowerCase().indexOf(word));
}

function completeCommands(word) {
	const words = constants.commands.slice();

	return fuzzyGrep(word, words);
}

function completeChans(word) {
	const words = [];

	for (const channel of store.state.activeChannel.network.channels) {
		// Push all channels that start with the same CHANTYPE
		if (channel.type === "channel" && channel.name[0] === word[0]) {
			words.push(channel.name);
		}
	}

	return fuzzyGrep(word, words);
}
<|endoftext|>


<commit_before>;(function(exports) {

    var game = new Phaser.Game(BubbleShoot.UI.width, BubbleShoot.UI.height, Phaser.CANVAS);
    game.state.add('boot', Boot);
    game.state.add('preloader', Preloader);
    game.state.add('menu', Menu);
    game.state.add('room', Room);
    game.state.add('room-create', RoomCreate);
    game.state.add('game', Game);
    game.state.start('boot');

    BubbleShoot.game = game;

})(this);
<commit_msg>fixed<commit_after>;(function(exports) {

    var game = new Phaser.Game(BubbleShoot.UI.width, BubbleShoot.UI.height, Phaser.AUTO);
    game.state.add('boot', Boot);
    game.state.add('preloader', Preloader);
    game.state.add('menu', Menu);
    game.state.add('room', Room);
    game.state.add('room-create', RoomCreate);
    game.state.add('game', Game);
    game.state.start('boot');

    BubbleShoot.game = game;

})(this);
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012-2015  Jochen S. Klar <jklar@aip.de>,
 *                           Adrian M. Partl <apartl@aip.de>,
 *                           Ondrej Jaura <ojaura@aip.de>,
 *                           AIP E-Science (www.aip.de)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

angular.module('simbadResolver',['browser'])

// Factory for Simbad queries
.factory('SimbadParser',['$http',function ($http) {

  // Search on Simbad and parse the data
  function simbadSearch(query,callBack) {

    // Correct the query
    query = query.replace(" ","+");

    /*
     * Simbad query URL
     * more information and settings at:
     * http://simbad.u-strasbg.fr/simbad/sim-help?Page=sim-url
     * http://simbad.u-strasbg.fr/simbad/sim-help?Page=sim-fscript#VotableFields
     */
    var url = "http://simbad.u-strasbg.fr/simbad/sim-id?Ident="+query+"&output.format=votable&output.params=main_id,coo(d),otype(V)"

    // get and parse the XML VOTable
    $http({
       method: 'GET',
       url: url
    }).then(function successCallback(response) {
       xmlDoc = $.parseXML(response.data);
       $xml = $(xmlDoc);
       rows = $xml.find('TABLEDATA TR')
       data = []
       rows.each(function(i){
         cols = $(this).find('TD');
         data[i] = {
           object: cols.eq(0).text(),
           type: cols.eq(6).text(),
           coord1: cols.eq(1).text(),
           coord2: cols.eq(2).text(),
         }
       });
       callBack(data);
    }, function errorCallback(response) {
       alert(response.data);
    });

  }

  return {
    simbadSearch: simbadSearch,
  };

}])

//Controller for a Simbad search form
.controller('simbadForm', ['$scope','SimbadParser',function ($scope,SimbadParser) {

  $scope.query = ''; // contains a input field string
  $scope.result = {cols:"",show:false}; // contains results from simbad

  // Perform a Simbad search and get the data
  $scope.simbadSearch = function () {
    if ($scope.query!="") {
      SimbadParser.simbadSearch($scope.query,function(data){
        $scope.result.data = data;
        $scope.result.query = $scope.query;
        $scope.result.show = true;
      });
    }
  }

  // Insert coordinates into the query text field
  // event is handled in 'query.js' file
  $scope.browserItemDblClicked = function(browsername,coord1,coord2) {
    if (coord1!="")
      $scope.$emit('browserItemDblClicked',browsername,coord1+' '+coord2);
    else
      alert('No coordinates available.')
  };

}]);

<commit_msg>whitespaces and semicolons<commit_after>/*
 *  Copyright (c) 2012-2015  Jochen S. Klar <jklar@aip.de>,
 *                           Adrian M. Partl <apartl@aip.de>,
 *                           Ondrej Jaura <ojaura@aip.de>,
 *                           AIP E-Science (www.aip.de)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

angular.module('simbadResolver',['browser'])

// Factory for Simbad queries
.factory('SimbadParser',['$http',function ($http) {

    // Search on Simbad and parse the data
    function simbadSearch(query,callBack) {

        // Correct the query
        query = query.replace(" ","+");

        /*
         * Simbad query URL
         * more information and settings at:
         * http://simbad.u-strasbg.fr/simbad/sim-help?Page=sim-url
         * http://simbad.u-strasbg.fr/simbad/sim-help?Page=sim-fscript#VotableFields
         */
        var url = "http://simbad.u-strasbg.fr/simbad/sim-id?Ident="+query+"&output.format=votable&output.params=main_id,coo(d),otype(V)";

        // get and parse the XML VOTable
        $http({
           method: 'GET',
           url: url
        }).then(function successCallback(response) {
            xmlDoc = $.parseXML(response.data);
            $xml = $(xmlDoc);
            rows = $xml.find('TABLEDATA TR');
            data = [];
            rows.each(function(i) {
                cols = $(this).find('TD');
                data[i] = {
                    object: cols.eq(0).text(),
                    type: cols.eq(6).text(),
                    coord1: cols.eq(1).text(),
                    coord2: cols.eq(2).text(),
                };
            });
            callBack(data);
        }, function errorCallback(response) {
            alert(response.data);
        });
    }

    return {
        simbadSearch: simbadSearch
    };
}])

//Controller for a Simbad search form
.controller('simbadForm', ['$scope','SimbadParser',function ($scope,SimbadParser) {

    $scope.query = ''; // contains a input field string
    $scope.result = {cols:"",show:false}; // contains results from simbad

    // Perform a Simbad search and get the data
    $scope.simbadSearch = function () {
        if ($scope.query !== "") {
            SimbadParser.simbadSearch($scope.query,function(data){
                $scope.result.data = data;
                $scope.result.query = $scope.query;
                $scope.result.show = true;
            });
        }
    };

    // Insert coordinates into the query text field
    // event is handled in 'query.js' file
    $scope.browserItemDblClicked = function(browsername,coord1,coord2) {
        if (coord1 !== "") {
            $scope.$emit('browserItemDblClicked',browsername,coord1+' '+coord2);
        } else {
            alert('No coordinates available.');
        }
    };
}]);
<|endoftext|>


<commit_before>var loopback = require('loopback');
var boot = require('loopback-boot');

var client = module.exports = loopback();

client.on('booted', function () {
    console.log("Booted!");
});

boot(client);

var localSQLiteDS = null;

if (window.cordova) {

    // { Create sqlite datasource programatically

    client.sqlite = require('loopback-connector-cordova-sqlite');
//    client.connector('sqlite', client.sqlite);
    localSQLiteDS = loopback.createDataSource('localSQLite', {
        connector: client.sqlite,
//        debug: true
    });

    // } --

    // {
    // Attach relevant models to the newly created sqite datasource.
    // Need to see if all candidate models can be elegantly attached,
    // without having to name each model separately.

//    client.models.LocalTodo.attachTo(client.dataSources.localSQLite);
    client.models.LocalTodo.attachTo(localSQLiteDS);

    // } --

    // { automigrate or autoupdate, whichever!
    //var localSqlite = client.datasources.localSQLite;
    var localSqlite = localSQLiteDS;
//var db = app.dataSources.db;
//var mysqlDs = app.dataSources.mysqlDs;
//var mongodbDs = app.dataSources.mongodbDs;

    function createSchema(dataSource_a) {
//    dataSource_a.autoupdate(function (error_a) {
        dataSource_a.automigrate(null, function (error_a) {

            if (error_a) {
                console.log("Error in autoupdate!");
            }
            else {
                console.log("Done!");
//            dataSource_a.disconnect();
            }
        });
    }

    createSchema(localSqlite);
    // } --

    // { Close DB on app going into background, need to check for app close as well.
    document.addEventListener("pause", function handleAppClose() {
//        client.datasources.localSQLite.disconnect();
        localSqlite.disconnect();
    }, false);
    // } --

}
else {
    // { In Desktop mode, depend on local storage, instead of sqlite.
    // } --
}

<commit_msg>Bugfix: Performed automigrate/autoupdate only after localSQLiteDS datasource received 'connected' event.<commit_after>var loopback = require('loopback');
var boot = require('loopback-boot');

var client = module.exports = loopback();

client.on('booted', function () {
    console.log("Booted!");
});

boot(client);

var localSQLiteDS = null;

if (window.cordova) {

    // { Create sqlite datasource programatically

    client.sqlite = require('loopback-connector-cordova-sqlite');
//    client.connector('sqlite', client.sqlite);
    localSQLiteDS = loopback.createDataSource('localSQLite', {
        connector: client.sqlite,
//        debug: true
    });

    localSQLiteDS.on('connected', function() {
        // {
        // Attach relevant models to the newly created sqite datasource.
        // Need to see if all candidate models can be elegantly attached,
        // without having to name each model separately.

//    client.models.LocalTodo.attachTo(client.dataSources.localSQLite);
        client.models.LocalTodo.attachTo(localSQLiteDS);

        // } --

        // { automigrate or autoupdate, whichever!
        //var localSqlite = client.datasources.localSQLite;
        var localSqlite = localSQLiteDS;
//var db = app.dataSources.db;
//var mysqlDs = app.dataSources.mysqlDs;
//var mongodbDs = app.dataSources.mongodbDs;

        function createSchema(dataSource_a) {
//    dataSource_a.autoupdate(function (error_a) {
            dataSource_a.automigrate(null, function (error_a) {

                if (error_a) {
                    console.log("Error in autoupdate!");
                }
                else {
                    console.log("Done!");
//            dataSource_a.disconnect();
                }
            });
        }

        createSchema(localSqlite);
        // } --

        // { Close DB on app going into background, need to check for app close as well.
        document.addEventListener("pause", function handleAppClose() {
//        client.datasources.localSQLite.disconnect();
            localSqlite.disconnect();
        }, false);
        // } --
    });

    // } --
}
else {
    // { In Desktop mode, depend on local storage, instead of sqlite.
    // } --
}

<|endoftext|>


<commit_before>

var extend = function(Parent, props) {
    var Type = function() {
        this.constructor.apply(this, arguments);
    };
    var constructor = Parent.prototype.constructor;
    Parent.prototype.constructor = function() {};
    var prototype = new Parent();
    if (constructor === undefined) {
        delete Parent.prototype.constructor;
    } else {
        Parent.prototype.constructor = constructor;
    }
    for (var key in props) {
        if (props.hasOwnProperty(key)) {
            prototype[key] = props[key];
        }
    }
    if (prototype.hasOwnProperty("toFullString") && !prototype.hasOwnProperty("toString")) {
        prototype.toString = function() {
            var str = this.toFullString();
            if (str.length > 60) {
                str = str.substring(0, 60) + "...";
            }
            return "<" + this.constructor.name + " " + str + ">";
        }
    }
    Type.prototype = prototype;
    return Type;
};

var toURL = function(o) {
    var url;
    if (o instanceof java.net.URL) {
        url = obj;
    } else if (o instanceof java.net.URI || o instanceof java.io.File) {
        url = o.toURL();
    } else if (typeof o === "string") {
        url = (new java.io.File(o)).toURL();
    }
    return url;
};

var toFile = function(o) {
    var file;
    if (o instanceof java.io.File) {
        file = o;
    } else if (o instanceof java.net.URI) {
        file = toFile(o.toURL());
    } else if (o instanceof java.net.URL) {
        file = toFile(o.getFile());
    } else if (typeof o === "string") {
        file = new java.io.File(o);
    }
}

exports.extend = extend;
exports.toURL = toURL;
exports.toFile = toFile;
<commit_msg>Support getters and setters using util.extend.<commit_after>

var extend = function(Parent, props) {
    var Type = function() {
        this.constructor.apply(this, arguments);
    };
    var constructor = Parent.prototype.constructor;
    Parent.prototype.constructor = function() {};
    var prototype = new Parent();
    if (constructor === undefined) {
        delete Parent.prototype.constructor;
    } else {
        Parent.prototype.constructor = constructor;
    }
    var getter, setter, straight;
    for (var name in props) {
        if (props.hasOwnProperty(name)) {
            getter = props.__lookupGetter__(name);
            setter = props.__lookupSetter__(name);
            straight = true;
            if (typeof getter === "function") {
                prototype.__defineGetter__(name, getter);
                straight = false;
            }
            if (typeof setter === "function") {
                prototype.__defineSetter__(name, setter);
                straight = false;
            }
            if (straight) {
                prototype[name] = props[name];
            }
        }
    }
    if (prototype.hasOwnProperty("toFullString") && !prototype.hasOwnProperty("toString")) {
        prototype.toString = function() {
            var str = this.toFullString();
            if (str.length > 60) {
                str = str.substring(0, 60) + "...";
            }
            return "<" + this.constructor.name + " " + str + ">";
        }
    }
    Type.prototype = prototype;
    return Type;
};

var toURL = function(o) {
    var url;
    if (o instanceof java.net.URL) {
        url = obj;
    } else if (o instanceof java.net.URI || o instanceof java.io.File) {
        url = o.toURL();
    } else if (typeof o === "string") {
        url = (new java.io.File(o)).toURL();
    }
    return url;
};

var toFile = function(o) {
    var file;
    if (o instanceof java.io.File) {
        file = o;
    } else if (o instanceof java.net.URI) {
        file = toFile(o.toURL());
    } else if (o instanceof java.net.URL) {
        file = toFile(o.getFile());
    } else if (typeof o === "string") {
        file = new java.io.File(o);
    }
}

exports.extend = extend;
exports.toURL = toURL;
exports.toFile = toFile;
<|endoftext|>


<commit_before>// Pressing `Escape` should close the last opened “element” and only the last
// one. Components can register themselves using a label a condition, and an
// action. This is used by Popup or inlinedForm for instance. When we press
// escape we execute the action which have a valid condition and his the highest
// in the label hierarchy.
EscapeActions = {
  _nextclickPrevented: false,

  _actions: [],

  // Executed in order
  hierarchy: [
    'textcomplete',
    'popup-back',
    'popup-close',
    'modalWindow',
    'inlinedForm',
    'detailsPane',
    'multiselection',
    'sidebarView',
  ],

  register(label, action, condition = () => true, options = {}) {
    const priority = this.hierarchy.indexOf(label);
    if (priority === -1) {
      throw Error('You must define the label in the EscapeActions hierarchy');
    }

    let enabledOnClick = options.enabledOnClick;
    if (_.isUndefined(enabledOnClick)) {
      enabledOnClick = true;
    }

    const noClickEscapeOn = options.noClickEscapeOn;

    this._actions = _.sortBy([...this._actions, {
      priority,
      condition,
      action,
      noClickEscapeOn,
      enabledOnClick,
    }], (action) => action.priority);
  },

  executeLowest() {
    return this._execute({
      multipleAction: false,
    });
  },

  executeAll() {
    return this._execute({
      multipleActions: true,
    });
  },

  executeUpTo(maxLabel) {
    return this._execute({
      maxLabel,
      multipleActions: true,
    });
  },

  clickExecute(target, maxLabel) {
    if (this._nextclickPrevented) {
      this._nextclickPrevented = false;
      return false;
    } else {
      return this._execute({
        maxLabel,
        multipleActions: false,
        isClick: true,
        clickTarget: target,
      });
    }
  },

  preventNextClick() {
    this._nextclickPrevented = true;
  },

  _stopClick(action, clickTarget) {
    if (!_.isString(action.noClickEscapeOn))
      return false;
    else
      return $(clickTarget).closest(action.noClickEscapeOn).length > 0;
  },

  _execute(options) {
    const maxLabel = options.maxLabel;
    const multipleActions = options.multipleActions;
    const isClick = Boolean(options.isClick);
    const clickTarget = options.clickTarget;

    let executedAtLeastOne = false;
    let maxPriority;

    if (!maxLabel)
      maxPriority = Infinity;
    else
      maxPriority = this.hierarchy.indexOf(maxLabel);

    for (const currentAction of this._actions) {
      if (currentAction.priority > maxPriority)
        return executedAtLeastOne;

      if (isClick && this._stopClick(currentAction, clickTarget))
        return executedAtLeastOne;

      const isEnabled = currentAction.enabledOnClick || !isClick;
      if (isEnabled && currentAction.condition()) {
        currentAction.action();
        executedAtLeastOne = true;
        if (!multipleActions)
          return executedAtLeastOne;
      }
    }
    return executedAtLeastOne;
  },
};

// Pressing escape to execute one escape action. We use `bindGloabal` vecause
// the shortcut sould work on textarea and inputs as well.
Mousetrap.bindGlobal('esc', () => {
  EscapeActions.executeLowest();
});

// On a left click on the document, we try to exectute one escape action (eg,
// close the popup). We don't execute any action if the user has clicked on a
// link or a button.
$(document).on('click', (evt) => {
  if (evt.button === 0 &&
    $(evt.target).closest('a,button,.is-editable').length === 0) {
    EscapeActions.clickExecute(evt.target, 'multiselection');
  }
});
<commit_msg>Fix typo of multipleActions<commit_after>// Pressing `Escape` should close the last opened “element” and only the last
// one. Components can register themselves using a label a condition, and an
// action. This is used by Popup or inlinedForm for instance. When we press
// escape we execute the action which have a valid condition and his the highest
// in the label hierarchy.
EscapeActions = {
  _nextclickPrevented: false,

  _actions: [],

  // Executed in order
  hierarchy: [
    'textcomplete',
    'popup-back',
    'popup-close',
    'modalWindow',
    'inlinedForm',
    'detailsPane',
    'multiselection',
    'sidebarView',
  ],

  register(label, action, condition = () => true, options = {}) {
    const priority = this.hierarchy.indexOf(label);
    if (priority === -1) {
      throw Error('You must define the label in the EscapeActions hierarchy');
    }

    let enabledOnClick = options.enabledOnClick;
    if (_.isUndefined(enabledOnClick)) {
      enabledOnClick = true;
    }

    const noClickEscapeOn = options.noClickEscapeOn;

    this._actions = _.sortBy([...this._actions, {
      priority,
      condition,
      action,
      noClickEscapeOn,
      enabledOnClick,
    }], (action) => action.priority);
  },

  executeLowest() {
    return this._execute({
      multipleActions: false,
    });
  },

  executeAll() {
    return this._execute({
      multipleActions: true,
    });
  },

  executeUpTo(maxLabel) {
    return this._execute({
      maxLabel,
      multipleActions: true,
    });
  },

  clickExecute(target, maxLabel) {
    if (this._nextclickPrevented) {
      this._nextclickPrevented = false;
      return false;
    } else {
      return this._execute({
        maxLabel,
        multipleActions: false,
        isClick: true,
        clickTarget: target,
      });
    }
  },

  preventNextClick() {
    this._nextclickPrevented = true;
  },

  _stopClick(action, clickTarget) {
    if (!_.isString(action.noClickEscapeOn))
      return false;
    else
      return $(clickTarget).closest(action.noClickEscapeOn).length > 0;
  },

  _execute(options) {
    const maxLabel = options.maxLabel;
    const multipleActions = options.multipleActions;
    const isClick = Boolean(options.isClick);
    const clickTarget = options.clickTarget;

    let executedAtLeastOne = false;
    let maxPriority;

    if (!maxLabel)
      maxPriority = Infinity;
    else
      maxPriority = this.hierarchy.indexOf(maxLabel);

    for (const currentAction of this._actions) {
      if (currentAction.priority > maxPriority)
        return executedAtLeastOne;

      if (isClick && this._stopClick(currentAction, clickTarget))
        return executedAtLeastOne;

      const isEnabled = currentAction.enabledOnClick || !isClick;
      if (isEnabled && currentAction.condition()) {
        currentAction.action();
        executedAtLeastOne = true;
        if (!multipleActions)
          return executedAtLeastOne;
      }
    }
    return executedAtLeastOne;
  },
};

// Pressing escape to execute one escape action. We use `bindGloabal` vecause
// the shortcut sould work on textarea and inputs as well.
Mousetrap.bindGlobal('esc', () => {
  EscapeActions.executeLowest();
});

// On a left click on the document, we try to exectute one escape action (eg,
// close the popup). We don't execute any action if the user has clicked on a
// link or a button.
$(document).on('click', (evt) => {
  if (evt.button === 0 &&
    $(evt.target).closest('a,button,.is-editable').length === 0) {
    EscapeActions.clickExecute(evt.target, 'multiselection');
  }
});
<|endoftext|>


<commit_before>var util      = require("util");
var Exception = require("./Exception");
var Buff      = require("./Buffer");

load();

exports.Exception = Exception;
exports.Package   = function (fcode, data) {
	var buffer = Buff.alloc(data.length + 1);

	buffer.writeUInt8(fcode, 0);
	Buff.from(data).copy(buffer, 1);

	return buffer;
};

Exception.load(exports);

function load() {
	var files = require("fs").readdirSync(__dirname + "/protocol");

	files.map(function (file) {
		if (file.substr(file.length - 3) != ".js") return;

		var funct     = require("./protocol/" + file);
		var camelName = file[0].toUpperCase() + file.substr(1, file.length - 4).toLowerCase().replace(/_(\w)/g, function (m, c) {
			return c.toUpperCase();
		});

		exports[camelName] = {
			Code     : funct.code,
			Request  : {
				build : proxy(funct, "buildRequest"),
				parse : function (buffer) {
					// byte 1 is function code
					return funct.parseRequest(buffer.slice(1));
				}
			},
			Response : {
				build : proxy(funct, "buildResponse"),
				parse : function (buffer) {
					// byte 1 is function code
					return funct.parseResponse(buffer.slice(1));
				}
			}
		};
	});

	exports.Request = function (buffer) {
		var code = buffer.readUInt8(0);

		for (var k in exports) {
			if (typeof exports[k] == "object" && exports[k].Code == code) {
				var data = exports[k].Request.parse(buffer);

				if (typeof data == "object" && !util.isArray(data)) {
					data.code = k;
				} else {
					data = { code: k, data: data };
				}

				return data;
			}
		}

		return {
			code : buffer[0],
			data : buffer.slice(1)
		};
	};

	exports.Response = function (buffer) {
		var code = buffer.readUInt8(0);

		if (!!(code & 0x80)) {
			return Exception.parse(buffer);
		}

		for (var k in exports) {
			if (typeof exports[k] == "object" && exports[k].Code == code) {
				var data = exports[k].Response.parse(buffer);

				if (typeof data == "object" && !util.isArray(data)) {
					data.code = k;
				} else {
					data = { code: k, data: data };
				}

				return data;
			}
		}

		return {
			code : buffer[0],
			data : buffer.slice(1)
		};
	};
}

function proxy(funct, method) {
	return function () {
		var stream = funct[method].apply(funct, arguments);
		var buffer = Buff.alloc(stream.length + 1);

		buffer[0] = funct.code;

		stream.copy(buffer, 1);

		return buffer;
	};
}
<commit_msg>avoid require() inline<commit_after>var fs        = require("fs");
var util      = require("util");
var path      = require("path");
var Exception = require("./Exception");
var Buff      = require("./Buffer");

load();

exports.Exception = Exception;
exports.Package   = function (fcode, data) {
	var buffer = Buff.alloc(data.length + 1);

	buffer.writeUInt8(fcode, 0);
	Buff.from(data).copy(buffer, 1);

	return buffer;
};

Exception.load(exports);

function load() {
	var files = fs.readdirSync(path.resolve(__dirname, "protocol"));

	files.map(function (file) {
		if (file.substr(file.length - 3) != ".js") return;

		var funct     = require("./protocol/" + file);
		var camelName = file[0].toUpperCase() + file.substr(1, file.length - 4).toLowerCase().replace(/_(\w)/g, function (m, c) {
			return c.toUpperCase();
		});

		exports[camelName] = {
			Code     : funct.code,
			Request  : {
				build : proxy(funct, "buildRequest"),
				parse : function (buffer) {
					// byte 1 is function code
					return funct.parseRequest(buffer.slice(1));
				}
			},
			Response : {
				build : proxy(funct, "buildResponse"),
				parse : function (buffer) {
					// byte 1 is function code
					return funct.parseResponse(buffer.slice(1));
				}
			}
		};
	});

	exports.Request = function (buffer) {
		var code = buffer.readUInt8(0);

		for (var k in exports) {
			if (typeof exports[k] == "object" && exports[k].Code == code) {
				var data = exports[k].Request.parse(buffer);

				if (typeof data == "object" && !util.isArray(data)) {
					data.code = k;
				} else {
					data = { code: k, data: data };
				}

				return data;
			}
		}

		return {
			code : buffer[0],
			data : buffer.slice(1)
		};
	};

	exports.Response = function (buffer) {
		var code = buffer.readUInt8(0);

		if (!!(code & 0x80)) {
			return Exception.parse(buffer);
		}

		for (var k in exports) {
			if (typeof exports[k] == "object" && exports[k].Code == code) {
				var data = exports[k].Response.parse(buffer);

				if (typeof data == "object" && !util.isArray(data)) {
					data.code = k;
				} else {
					data = { code: k, data: data };
				}

				return data;
			}
		}

		return {
			code : buffer[0],
			data : buffer.slice(1)
		};
	};
}

function proxy(funct, method) {
	return function () {
		var stream = funct[method].apply(funct, arguments);
		var buffer = Buff.alloc(stream.length + 1);

		buffer[0] = funct.code;

		stream.copy(buffer, 1);

		return buffer;
	};
}
<|endoftext|>