<commit_before>'use strict';

angular.module('myApp.newpost', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/newpost', {
        templateUrl: 'newpost/newpost.html',
        controller: 'NewPostCtrl'
    });
}])

.controller('NewPostCtrl', ['$scope','$firebase','CommonProp', '$location', function($scope,$firebase,CommonProp,$location) {
	$scope.content="";
    var uid = CommonProp.getUser();
    var firebaseObject = new Firebase("https://resplendent-heat-9609.firebaseio.com");
    var syncLang = $firebase(firebaseObject.child('Tags/Language'));
    var syncFandom = $firebase(firebaseObject.child('Tags/Fandom'));
    var syncGenre = $firebase(firebaseObject.child('Tags/Genre'));
    $scope.languages = syncLang.$asArray();
    $scope.fandoms = syncFandom.$asArray();
    $scope.genres = syncGenre.$asArray();
    $scope.langSelection = [];
    $scope.fandomSelection = [];
    $scope.genreSelection = [];

    // for selecting preferred languages
    $scope.toggleLang = function(lang) {
        var idx = $scope.langSelection.indexOf(lang);
        if (idx > -1) {
            $scope.langSelection.splice(idx, 1);
        }
        else {
            $scope.langSelection.push(lang);
        }
    };

    // for selecting preferred fandoms
    $scope.toggleFandom = function(fandom) {
        var idx = $scope.fandomSelection.indexOf(fandom);
        if (idx > -1) {
            $scope.fandomSelection.splice(idx, 1);
        }
        else {
            $scope.fandomSelection.push(fandom);
        }
    };

    // for selecting preferred genres
    $scope.toggleGenre = function(genre) {
        var idx = $scope.genreSelection.indexOf(genre);
        if (idx > -1) {
            $scope.genreSelection.splice(idx, 1);
        }
        else {
            $scope.genreSelection.push(genre);
        }
    };

    var firebaseObj = new Firebase("https://resplendent-heat-9609.firebaseio.com/Articles");

    $scope.fileUpload = function(element){
        var reader = new FileReader();
        reader.onload = $scope.fileIsLoaded;
        reader.readAsText(element.files[0]);
    };

    $scope.fileIsLoaded = function(e){
        $scope.$apply(function() {
            $scope.content=e.target.result;
        });
    };

    $scope.AddPost = function(){
		var title = $scope.article.title;
        var post = $scope.content;
		//Language, Genre, Comment ids

        var fb = $firebase(firebaseObj);
        var fanFlg = 1;
        var username = CommonProp.getUserName();

        if($scope.fanficFlg==false)
            fanFlg = 0;

		fb.$push({ title: title, post: post, uid: uid, username: username, transflag: 0, orig: "", translated: [], fanFlg: fanFlg, fandom: $scope.fandomSelection, genre: $scope.genreSelection, language: $scope.langSelection}).then(function(ref) {
            console.log(ref);
            $location.path('/account');
		}, function(error) {
            console.log("Error:", error);
		});

    };

    var sync = $firebase(firebaseObj.orderByChild("uid").equalTo(uid));
    $scope.articles = sync.$asArray();

    $scope.translatePost = function(id){
        CommonProp.setArticle(id);
    };
}]);<commit_msg>minor change to add new post firebase expression<commit_after>'use strict';

angular.module('myApp.newpost', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/newpost', {
        templateUrl: 'newpost/newpost.html',
        controller: 'NewPostCtrl'
    });
}])

.controller('NewPostCtrl', ['$scope','$firebase','CommonProp', '$location', function($scope,$firebase,CommonProp,$location) {
	$scope.content="";
    var uid = CommonProp.getUser();
    var firebaseObject = new Firebase("https://resplendent-heat-9609.firebaseio.com");
    var syncLang = $firebase(firebaseObject.child('Tags/Language'));
    var syncFandom = $firebase(firebaseObject.child('Tags/Fandom'));
    var syncGenre = $firebase(firebaseObject.child('Tags/Genre'));
    $scope.languages = syncLang.$asArray();
    $scope.fandoms = syncFandom.$asArray();
    $scope.genres = syncGenre.$asArray();
    $scope.langSelection = [];
    $scope.fandomSelection = [];
    $scope.genreSelection = [];

    // for selecting preferred languages
    $scope.toggleLang = function(lang) {
        var idx = $scope.langSelection.indexOf(lang);
        if (idx > -1) {
            $scope.langSelection.splice(idx, 1);
        }
        else {
            $scope.langSelection.push(lang);
        }
    };

    // for selecting preferred fandoms
    $scope.toggleFandom = function(fandom) {
        var idx = $scope.fandomSelection.indexOf(fandom);
        if (idx > -1) {
            $scope.fandomSelection.splice(idx, 1);
        }
        else {
            $scope.fandomSelection.push(fandom);
        }
    };

    // for selecting preferred genres
    $scope.toggleGenre = function(genre) {
        var idx = $scope.genreSelection.indexOf(genre);
        if (idx > -1) {
            $scope.genreSelection.splice(idx, 1);
        }
        else {
            $scope.genreSelection.push(genre);
        }
    };

    var firebaseObj = new Firebase("https://resplendent-heat-9609.firebaseio.com/Articles");

    $scope.fileUpload = function(element){
        var reader = new FileReader();
        reader.onload = $scope.fileIsLoaded;
        reader.readAsText(element.files[0]);
    };

    $scope.fileIsLoaded = function(e){
        $scope.$apply(function() {
            $scope.content=e.target.result;
        });
    };

    $scope.AddPost = function(){
		var title = $scope.article.title;
        var post = $scope.content;
		//Language, Genre, Comment ids

        var fb = $firebase(firebaseObj);
        var fanFlg = 1;
        var username = CommonProp.getUserName();

        if($scope.fanficFlg==false)
            fanFlg = 0;

		fb.$push({ title: title, post: post, uid: uid, username: username, transflag: 0, orig: "", translated: [], comments: [], fanFlg: fanFlg, fandom: $scope.fandomSelection, genre: $scope.genreSelection, language: $scope.langSelection}).then(function(ref) {
            console.log(ref);
            $location.path('/account');
		}, function(error) {
            console.log("Error:", error);
		});

    };

    var sync = $firebase(firebaseObj.orderByChild("uid").equalTo(uid));
    $scope.articles = sync.$asArray();

    $scope.translatePost = function(id){
        CommonProp.setArticle(id);
    };
}]);<|endoftext|>


<commit_before>/**  @author Michael Murphy */
define(['jquery', 'underscore', 'backbone', 'backbone.marionette', 'handlebars', 'app/app'], function($, _, Backbone, Marionette, Handlebars, app, template, app) {
   var Course = Backbone.Model.extend({
      idAttribute: "_id"
   });
   var Courses = Backbone.Collection.extend({
      model:Course,
      url: '/api/Course'
   });
});<commit_msg>fixed idAttribute<commit_after>/**  @author Michael Murphy */
define(['jquery', 'underscore', 'backbone', 'backbone.marionette', 'handlebars', 'app/app'], function($, _, Backbone, Marionette, Handlebars, app, template, app) {
   var Course = Backbone.Model.extend({
      idAttribute: "colloquialUrl"
   });
   var Courses = Backbone.Collection.extend({
      model:Course,
      url: '/api/Courses'
   });
});<|endoftext|>


<commit_before>const {
    FuseBox,
    CSSPlugin,
    WebIndexPlugin,
    Sparky,
    UglifyJSPlugin,
    QuantumPlugin,
    EnvPlugin
} = require("fuse-box");

const express = require("express");
const path = require("path");
const {spawn} = require("child_process");

let producer;
let production = false;

Sparky.task("build:renderer", () => {
    const fuse = FuseBox.init({
        homeDir: "src/renderer",
        sourceMaps: { project: true, vendor: true },
        output: "dist/renderer/$name.js",
        hash: production,
        target: "electron",
        experimentalFeatures: true,
        cache: !production,
        plugins: [
            EnvPlugin({ NODE_ENV: production ? "production" : "development" }),
            [CSSPlugin()],
            WebIndexPlugin({
                title: "FuseBox electron demo",
                template: "src/renderer/index.html",
                path: production ? "." : "/renderer/"
            }),
            production && QuantumPlugin({
                bakeApiIntoBundle : 'renderer',
                target : 'electron',
                treeshake: true,
                removeExportsInterop: false,
                uglify: true
            })
        ]
    });

    if (!production) {
        // Configure development server
        fuse.dev({ root: false }, server => {
            const dist = path.join(__dirname, "dist");
            const app = server.httpServer.app;
            app.use("/renderer/", express.static(path.join(dist, 'renderer')));
            app.use("/svg/", express.static(path.join(dist, 'renderer', 'svg')));
            app.get("/", function(req, res) {
                res.sendFile(path.join(dist, "renderer/index.html"));
            });
        })
    }

    const app = fuse.bundle("renderer")
        .instructions('> [index.tsx] + fuse-box-css')

    if (!production) {
        app.hmr().watch()
    }

    return fuse.run()
});

Sparky.task("build:main", () => {
    const fuse = FuseBox.init({
        homeDir: "src/main",
        sourceMaps: { project: true, vendor: true },
        output: "dist/main/$name.js",
        target: "server",
        experimentalFeatures: true,
        cache: !production,
        plugins: [
            EnvPlugin({ NODE_ENV: production ? "production" : "development" }),
            production && QuantumPlugin({
                bakeApiIntoBundle : 'main',
                target : 'server',
                treeshake: true,
                removeExportsInterop: false,
                uglify: true
            })
        ]
    });

    const app = fuse.bundle("main")
        .instructions('> [main.ts]')

    if (!production) {
        app.watch()

        return fuse.run().then(() => {
            // launch electron the app
            const child = spawn('npm', [ 'run', 'start:electron:watch' ]);
            child.stdout.on('data', function(data) {
                console.log(data.toString());
                //Here is where the output goes
            });
            child.stderr.on('data', function(data) {
                console.error(data.toString());
                //Here is where the error output goes
            });
        });
    }

    return fuse.run()
});

// main task
Sparky.task("default", ["clean:dist", "clean:cache", "copy-svg", "build:renderer", "build:main"], () => {});

Sparky.task("copy-svg", () => Sparky.src("src/renderer/svg/*.svg").dest("dist/renderer/svg/$name"));
// wipe it all
Sparky.task("clean:dist", () => Sparky.src("dist/*").clean("dist/"));
// wipe it all from .fusebox - cache dir
Sparky.task("clean:cache", () => Sparky.src(".fusebox/*").clean(".fusebox/"));

// prod build
Sparky.task("set-production-env", () => production = true);
Sparky.task("dist", ["clean:dist", "clean:cache", "set-production-env", "copy-svg", "build:main", "build:renderer"], () => {})
<commit_msg>fix styling<commit_after>const {
    FuseBox,
    CSSPlugin,
    WebIndexPlugin,
    Sparky,
    QuantumPlugin,
    EnvPlugin
} = require('fuse-box')

const express = require('express')
const path = require('path')
const {spawn} = require('child_process')

let production = false

Sparky.task('build:renderer', () => {
  const fuse = FuseBox.init({
    homeDir: 'src/renderer',
    sourceMaps: { project: true, vendor: true },
    output: 'dist/renderer/$name.js',
    hash: production,
    target: 'electron',
    experimentalFeatures: true,
    cache: !production,
    plugins: [
      EnvPlugin({ NODE_ENV: production ? 'production' : 'development' }),
            [CSSPlugin()],
      WebIndexPlugin({
        title: 'FuseBox electron demo',
        template: 'src/renderer/index.html',
        path: production ? '.' : '/renderer/'
      }),
      production && QuantumPlugin({
        bakeApiIntoBundle: 'renderer',
        target: 'electron',
        treeshake: true,
        removeExportsInterop: false,
        uglify: true
      })
    ]
  })

  if (!production) {
        // Configure development server
    fuse.dev({ root: false }, server => {
      const dist = path.join(__dirname, 'dist')
      const app = server.httpServer.app
      app.use('/renderer/', express.static(path.join(dist, 'renderer')))
      app.use('/svg/', express.static(path.join(dist, 'renderer', 'svg')))
      app.use('/fonts/', express.static(path.join(dist, 'renderer', 'fonts')))
      app.get('/', function (req, res) {
        res.sendFile(path.join(dist, 'renderer/index.html'))
      })
    })
  }

  const app = fuse.bundle('renderer')
        .instructions('> [index.tsx] + fuse-box-css')

  if (!production) {
    app.hmr().watch()
  }

  return fuse.run()
})

Sparky.task('build:main', () => {
  const fuse = FuseBox.init({
    homeDir: 'src/main',
    sourceMaps: { project: true, vendor: true },
    output: 'dist/main/$name.js',
    target: 'server',
    experimentalFeatures: true,
    cache: !production,
    plugins: [
      EnvPlugin({ NODE_ENV: production ? 'production' : 'development' }),
      production && QuantumPlugin({
        bakeApiIntoBundle: 'main',
        target: 'server',
        treeshake: true,
        removeExportsInterop: false,
        uglify: true
      })
    ]
  })

  const app = fuse.bundle('main')
        .instructions('> [main.ts]')

  if (!production) {
    app.watch()

    return fuse.run().then(() => {
            // launch electron the app
      const child = spawn('npm', [ 'run', 'start:electron:watch' ])
      child.stdout.on('data', function (data) {
        console.log(data.toString())
                // Here is where the output goes
      })
      child.stderr.on('data', function (data) {
        console.error(data.toString())
                // Here is where the error output goes
      })
    })
  }

  return fuse.run()
})

// main task
Sparky.task('default', ['clean:dist', 'clean:cache', 'copy-svg', 'copy-fonts', 'build:renderer', 'build:main'], () => {})

Sparky.task('copy-svg', () => Sparky.src('src/renderer/svg/*.svg').dest('dist/renderer/svg/$name'))
Sparky.task('copy-fonts', () => Sparky.src('src/renderer/fonts/*.*').dest('dist/renderer/fonts/$name'))
// wipe it all
Sparky.task('clean:dist', () => Sparky.src('dist/*').clean('dist/'))
// wipe it all from .fusebox - cache dir
Sparky.task('clean:cache', () => Sparky.src('.fusebox/*').clean('.fusebox/'))

// prod build
Sparky.task('set-production-env', () => production = true)
Sparky.task('dist', ['clean:dist', 'clean:cache', 'set-production-env', 'copy-svg', 'copy-fonts', 'build:main', 'build:renderer'], () => {})
<|endoftext|>


<commit_before>Number.prototype.toRad = function() {
   return this * Math.PI / 180;
}
Number.prototype.toDeg = function() {
   return this * 180 / Math.PI;
}

var Metros = function() {
  var nestedCities,
    geoJSONUrl,
    sceneURL,
    displayMap,
    extractLayers = [],
    xhr,
    keyIndex = -1,
    placeID = null;

  var rect,
    dots = [],
    outline,
    requestBoundingBox;

  var MetrosApp = {
    init : function(nestedData, jsonURL, scene) {
      nestedCities = nestedData;
      geoJSONUrl = jsonURL;
      sceneURL = scene;
      this.initDisplayMap();
      return this;
    },
    hasWebGL : function() {
      try {
        var canvas = document.createElement('canvas')
        return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')))
      } catch (x) {
        return false
      }
    },
    initDisplayMap : function() {
      var southwest = L.latLng(0, -125),
        northeast = L.latLng(0, 125),
        options = {
          scrollWheelZoom: false,
          // Disables dragging on touch-detected devices
          dragging: (window.self !== window.top && L.Browser.touch) ? false : true,
          tap: (window.self !== window.top && L.Browser.touch) ? false : true,
        };
      displayMap = L.map('map', options).fitBounds(L.latLngBounds(southwest, northeast));

      if (this.hasWebGL() === true) {
        var layer = Tangram.leafletLayer({
          scene: sceneURL,
          attribution: 'Tangram | © OSM contributors | Mapzen'
        });
      } else {
        var layer = L.tileLayer('https://stamen-tiles.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
          attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.',
        });
      }
      layer.addTo(displayMap);

      var onEachFeature = function (feature, layer) {
        extractLayers.push(layer);
        layer.bindPopup(""+feature.properties.display_name+"");
      }

      d3.json(geoJSONUrl, function(data){
        L.geoJson(data, { onEachFeature: onEachFeature }).addTo(displayMap);
      });
    },
    filterList : function(str) {
      var newData = [];
      str = str.toLowerCase();
      nestedCities.forEach(function(d){
        if (d.country.toLowerCase().indexOf(str) != -1) {
          newData.push(d);
        } else {
          var c = {
            country : d.country,
            metros : []
          }
          d.metros.forEach(function(e){
            if (e.name.toLowerCase().indexOf(str) != -1)
              c.metros.push(e);
          });
          if (c.metros.length) newData.push(c);
        }
      });
      this.drawList(newData);
    },
    drawList : function(data, request_id, display_name) {
      var countries = d3.select("#extracts").selectAll(".country").data(data);
      var enterCountries = countries.enter().append("div").attr("class","country");
      countries.exit().remove();
      enterCountries.append("div").attr("class","country-name")
      var m = this;
      countries.select(".country-name")
        .text(function(d){ return d.country; })
        .on("click",function(d){
          m.doSearch(d.country);
        });
      var cities = countries.selectAll(".city").data(function(d){ return d.metros; });
      cities.enter().append("a").attr("class","city");
      cities.text(function(d){ return d.name; })
        .attr("href",function(d){ return d.href + (request_id ? escape(request_id)+"/"+escape(display_name) : ""); });
      cities.exit().remove();
    },
    doSuggestion : function(query) {
      if (xhr) xhr.abort();
      var m = this;
      xhr = d3.json("https://search.mapzen.com/v1/autocomplete?text="+query+"&sources=wof&api_key=search-owZDPeC", function(error, json) {
        if (json.features.length)
          m.showSuggestions(json);
      });
    },
    showSuggestions : function(data) {
      var suggestion = d3.select(".autocomplete")
        .selectAll(".suggestion").data(data.features);
      suggestion.enter().append("div").attr("class","suggestion");
      suggestion.exit().remove();
      var m = this;
      suggestion.text(function(d){ return d.properties.label; })
        .on("click",function(d){
          placeID = d.properties.source + ":" + d.properties.layer + ":" + d.properties.id;
          m.onSubmit(d.properties.label);
        });
    },
    selectSuggestion : function() {
      var currentList = d3.selectAll(".suggestion");
      currentList.each(function(d, i){
        if (i == keyIndex) {
          document.getElementById("search_input").value = d.properties.label;
          placeID = d.properties.source + ":" + d.properties.layer + ":" + d.properties.id;
        }
      }).classed("selected",function(d,i){ return i == keyIndex; });
    },
    onSubmit : function(val) {
      keyIndex = -1;
      this.filterList(val);
      d3.selectAll(".suggestion").remove();
      this.doSearch(val);
      placeID = null;
    },
    suggestPlace : function(metro) {
      var m = this;
      d3.select("#did-you-mean").style("display","block")
        .select(".name").text(metro.properties.label)
        .on("click",function(){
          d3.select(this.parentNode).style("display","none");
          var bbox = metro.bbox;
          displayMap.fitBounds([[bbox[1],bbox[0]],[bbox[3], bbox[2]]]).zoomOut(1);
          document.getElementById("search_input").value = metro.properties.label;
          m.filterList(metro.properties.label);
          m.requestExtract(metro);
        });
      d3.select("#make-request").style("display","none");
    },
    processKeyup : function(event) {
      var inputDiv = document.getElementById("search_input");
      var val = inputDiv.value;

      if (!val.length) {
        this.drawList(nestedCities);
        d3.selectAll(".suggestion").remove();
        placeID = null;
        this.clearRequest();
        return;
      }

      if (event.keyCode == 40) { //arrow down
        keyIndex = Math.min(keyIndex+1, d3.selectAll(".suggestion")[0].length-1);
        this.selectSuggestion();
      } else if (event.keyCode == 38) { //arrow up
        keyIndex = Math.max(keyIndex-1, 0);
        this.selectSuggestion();
      } else if (event.keyCode == 13) { //enter
        this.onSubmit(val);
      } else if (event.keyCode != 8 && (event.keyCode < 48 || event.keyCode > 90)) {
        return; //restrict autocomplete to 0-9,a-z character input, excluding delete
      } else {
        keyIndex = -1;
        placeID = null;
        this.doSuggestion(val);
        this.filterList(val);
      }
    },
    doSearch : function(query) {
      d3.selectAll(".suggestion").remove();
      var m = this;

      if (placeID) {
        d3.json("https://search.mapzen.com/v1/place?api_key=search-owZDPeC&ids="+placeID, function(error, json){
          var bbox = json.features[0].bbox;
          displayMap.fitBounds([[bbox[1],bbox[0]],[bbox[3], bbox[2]]]).zoomOut(1);
          m.requestExtract(json.features[0]);
        });
      } else {
        d3.json("https://search.mapzen.com/v1/search?text="+query+"&sources=wof&api_key=search-owZDPeC", function(error, json) {
          if (json.features[0].properties.label.toLowerCase().indexOf(query.toLowerCase()) == -1
            && d3.selectAll(".city")[0].length == 0) {
            m.suggestPlace(json.features[0]);
          } else if (d3.selectAll(".city")[0].length == 0){
            var bbox = json.features[0].bbox;
            displayMap.fitBounds([[bbox[1],bbox[0]],[bbox[3], bbox[2]]]).zoomOut(1);
            document.getElementById("search_input").value = json.features[0].properties.label;
            m.requestExtract(json.features[0]);
          } else {
            m.clearRequest();
          }
        });
      }
    },
    requestExtract : function(metro) {
      var geoID = metro.properties.id;
      d3.select("input[name='wof_id']").attr("value",geoID);
      d3.select("input[name='wof_name']").attr("value",metro.properties.label);

      requestBoundingBox = this.calculateNewBox(metro.bbox);

      this.drawRequestBox();

      d3.json("wof/"+geoID+".geojson",function(data){
        outline = L.geoJson(data.geometry, { className : "outline" }).addTo(displayMap);
        displayMap.addLayer(outline);
      });

      var bbox = metro.bbox,
        p1 = L.latLng(bbox[1],bbox[0]),
        p2 = L.latLng(bbox[3],bbox[2]);
      var encompassed = [{
        country : "Encompassing Metros",
        metros : []
      }];
      extractLayers.forEach(function(l){
        if (l.getBounds().contains(p1) && l.getBounds().contains(p2))
          encompassed[0].metros.push({
            name : l.feature.properties.display_name,
            href : l.feature.properties.href,
            country : l.feature.properties.name.split("_")[1],
            bbox : l.feature.bbox
          })
      });

      var requestDiv = d3.select("#request-wrapper");

      requestDiv.select("#make-request")
        .style("display","block")
        .selectAll(".name").text(metro.properties.name);

      if (encompassed[0].metros.length){
        requestDiv.attr("class","encompassed");
        this.drawList(encompassed, geoID, metro.properties.name);
        return;
      }

      var biggestDist = Math.max(requestBoundingBox[1][1] - requestBoundingBox[0][1], requestBoundingBox[1][0] - requestBoundingBox[0][0]);
      if (biggestDist > 5)
        requestDiv.attr("class","request-greater-5");
      else if (biggestDist > 1)
        requestDiv.attr("class","request-greater-1");
      else
        requestDiv.attr("class","default");
    },
    clearMap : function() {
      if (rect) displayMap.removeLayer(rect);
      if (outline) displayMap.removeLayer(outline);
      dots.forEach(function(l){
        displayMap.removeLayer(l);
      });
      dots = [];
    },
    clearRequest : function() {
      this.clearMap();
      d3.select("#did-you-mean").style("display","none");
      d3.select("#make-request").style("display","none");
    },
    calculateOffset : function(theta, d, lat1, lng1) {
      var lat1 = lat1.toRad(),
        lng1 = lng1.toRad(),
        R = 6371;

      var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R)
            + Math.cos(lat1)*Math.sin(d/R)*Math.cos(theta) ),
        lng2 = lng1 + Math.atan2(Math.sin(theta)*Math.sin(d/R)*Math.cos(lat1),
              Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));

      return [lat2.toDeg(), lng2.toDeg()];
    },
    calculateNewBox : function(bbox) {
      var distance = Math.sqrt(Math.pow(bbox[3]-bbox[1],2) + Math.pow(bbox[2]-bbox[0], 2))*25,
        northEast = this.calculateOffset(-Math.PI*3/4, distance, bbox[1], bbox[0]),
        southWest = this.calculateOffset(Math.PI/4, distance, bbox[3], bbox[2]);
      return [northEast, southWest];
    },
    drawRequestBox : function() {
      this.clearMap();
      var m = this;
      rect = new L.Rectangle(new L.LatLngBounds(requestBoundingBox), { className : "blue" });
      displayMap.addLayer(rect);

      var myIcon = L.divIcon({className: 'drag-icon'});

      var cSW = new L.marker(requestBoundingBox[0], { icon : myIcon, draggable: true });
      dots.push(cSW);
      var cNE = new L.marker(requestBoundingBox[1], { icon : myIcon, draggable: true });
      dots.push(cNE);

      cSW.on("drag",function(e){
        requestBoundingBox[0] = [e.target.getLatLng().lat, e.target.getLatLng().lng];
        m.redrawBox();
      });
      cNE.on("drag",function(e){
        requestBoundingBox[1] = [e.target.getLatLng().lat, e.target.getLatLng().lng];
        m.redrawBox();
      });

      dots.forEach(function(l){
        displayMap.addLayer(l);
      });
      this.fillRequestForm();
    },
    redrawBox : function() {
      displayMap.removeLayer(rect);
      rect = new L.Rectangle(new L.LatLngBounds(requestBoundingBox), { className : "blue" });
      displayMap.addLayer(rect);
      this.fillRequestForm();
    },
    fillRequestForm : function() {
      d3.select("input[name='bbox_n']").attr("value",requestBoundingBox[1][0]);
      d3.select("input[name='bbox_w']").attr("value",requestBoundingBox[0][1]);
      d3.select("input[name='bbox_s']").attr("value",requestBoundingBox[0][0]);
      d3.select("input[name='bbox_e']").attr("value",requestBoundingBox[1][1]);
    }
  }
  return MetrosApp;
}<commit_msg>default to 10km radius for places returned as points<commit_after>Number.prototype.toRad = function() {
   return this * Math.PI / 180;
}
Number.prototype.toDeg = function() {
   return this * 180 / Math.PI;
}

var Metros = function() {
  var nestedCities,
    geoJSONUrl,
    sceneURL,
    displayMap,
    extractLayers = [],
    xhr,
    keyIndex = -1,
    placeID = null;

  var rect,
    dots = [],
    outline,
    requestBoundingBox;

  var MetrosApp = {
    init : function(nestedData, jsonURL, scene) {
      nestedCities = nestedData;
      geoJSONUrl = jsonURL;
      sceneURL = scene;
      this.initDisplayMap();
      return this;
    },
    hasWebGL : function() {
      try {
        var canvas = document.createElement('canvas')
        return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')))
      } catch (x) {
        return false
      }
    },
    initDisplayMap : function() {
      var southwest = L.latLng(0, -125),
        northeast = L.latLng(0, 125),
        options = {
          scrollWheelZoom: false,
          // Disables dragging on touch-detected devices
          dragging: (window.self !== window.top && L.Browser.touch) ? false : true,
          tap: (window.self !== window.top && L.Browser.touch) ? false : true,
        };
      displayMap = L.map('map', options).fitBounds(L.latLngBounds(southwest, northeast));

      if (this.hasWebGL() === true) {
        var layer = Tangram.leafletLayer({
          scene: sceneURL,
          attribution: 'Tangram | © OSM contributors | Mapzen'
        });
      } else {
        var layer = L.tileLayer('https://stamen-tiles.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.png', {
          attribution: 'Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL.',
        });
      }
      layer.addTo(displayMap);

      var onEachFeature = function (feature, layer) {
        extractLayers.push(layer);
        layer.bindPopup(""+feature.properties.display_name+"");
      }

      d3.json(geoJSONUrl, function(data){
        L.geoJson(data, { onEachFeature: onEachFeature }).addTo(displayMap);
      });
    },
    filterList : function(str) {
      var newData = [];
      str = str.toLowerCase();
      nestedCities.forEach(function(d){
        if (d.country.toLowerCase().indexOf(str) != -1) {
          newData.push(d);
        } else {
          var c = {
            country : d.country,
            metros : []
          }
          d.metros.forEach(function(e){
            if (e.name.toLowerCase().indexOf(str) != -1)
              c.metros.push(e);
          });
          if (c.metros.length) newData.push(c);
        }
      });
      this.drawList(newData);
    },
    drawList : function(data, request_id, display_name) {
      var countries = d3.select("#extracts").selectAll(".country").data(data);
      var enterCountries = countries.enter().append("div").attr("class","country");
      countries.exit().remove();
      enterCountries.append("div").attr("class","country-name")
      var m = this;
      countries.select(".country-name")
        .text(function(d){ return d.country; })
        .on("click",function(d){
          m.doSearch(d.country);
        });
      var cities = countries.selectAll(".city").data(function(d){ return d.metros; });
      cities.enter().append("a").attr("class","city");
      cities.text(function(d){ return d.name; })
        .attr("href",function(d){ return d.href + (request_id ? escape(request_id)+"/"+escape(display_name) : ""); });
      cities.exit().remove();
    },
    doSuggestion : function(query) {
      if (xhr) xhr.abort();
      var m = this;
      xhr = d3.json("https://search.mapzen.com/v1/autocomplete?text="+query+"&sources=wof&api_key=search-owZDPeC", function(error, json) {
        if (json.features.length)
          m.showSuggestions(json);
      });
    },
    showSuggestions : function(data) {
      var suggestion = d3.select(".autocomplete")
        .selectAll(".suggestion").data(data.features);
      suggestion.enter().append("div").attr("class","suggestion");
      suggestion.exit().remove();
      var m = this;
      suggestion.text(function(d){ return d.properties.label; })
        .on("click",function(d){
          placeID = d.properties.source + ":" + d.properties.layer + ":" + d.properties.id;
          m.onSubmit(d.properties.label);
        });
    },
    selectSuggestion : function() {
      var currentList = d3.selectAll(".suggestion");
      currentList.each(function(d, i){
        if (i == keyIndex) {
          document.getElementById("search_input").value = d.properties.label;
          placeID = d.properties.source + ":" + d.properties.layer + ":" + d.properties.id;
        }
      }).classed("selected",function(d,i){ return i == keyIndex; });
    },
    onSubmit : function(val) {
      keyIndex = -1;
      this.filterList(val);
      d3.selectAll(".suggestion").remove();
      this.doSearch(val);
      placeID = null;
    },
    suggestPlace : function(metro) {
      var m = this;
      d3.select("#did-you-mean").style("display","block")
        .select(".name").text(metro.properties.label)
        .on("click",function(){
          d3.select(this.parentNode).style("display","none");
          document.getElementById("search_input").value = metro.properties.label;
          m.filterList(metro.properties.label);
          m.requestExtract(metro);
        });
      d3.select("#make-request").style("display","none");
    },
    processKeyup : function(event) {
      var inputDiv = document.getElementById("search_input");
      var val = inputDiv.value;

      if (!val.length) {
        this.drawList(nestedCities);
        d3.selectAll(".suggestion").remove();
        placeID = null;
        this.clearRequest();
        return;
      }

      if (event.keyCode == 40) { //arrow down
        keyIndex = Math.min(keyIndex+1, d3.selectAll(".suggestion")[0].length-1);
        this.selectSuggestion();
      } else if (event.keyCode == 38) { //arrow up
        keyIndex = Math.max(keyIndex-1, 0);
        this.selectSuggestion();
      } else if (event.keyCode == 13) { //enter
        this.onSubmit(val);
      } else if (event.keyCode != 8 && (event.keyCode < 48 || event.keyCode > 90)) {
        return; //restrict autocomplete to 0-9,a-z character input, excluding delete
      } else {
        keyIndex = -1;
        placeID = null;
        this.doSuggestion(val);
        this.filterList(val);
      }
    },
    doSearch : function(query) {
      d3.selectAll(".suggestion").remove();
      var m = this;

      if (placeID) {
        d3.json("https://search.mapzen.com/v1/place?api_key=search-owZDPeC&ids="+placeID, function(error, json){
          m.requestExtract(json.features[0]);
        });
      } else {
        d3.json("https://search.mapzen.com/v1/search?text="+query+"&sources=wof&api_key=search-owZDPeC", function(error, json) {
          if (json.features[0].properties.label.toLowerCase().indexOf(query.toLowerCase()) == -1
            && d3.selectAll(".city")[0].length == 0) {
            m.suggestPlace(json.features[0]);
          } else if (d3.selectAll(".city")[0].length == 0){
            document.getElementById("search_input").value = json.features[0].properties.label;
            m.requestExtract(json.features[0]);
          } else {
            m.clearRequest();
          }
        });
      }
    },
    requestExtract : function(metro) {

      var bbox = metro.bbox,
        zoomOut = (metro.geometry.type == "Point") ? 7 : 1;
      displayMap.fitBounds([[bbox[1],bbox[0]],[bbox[3], bbox[2]]]).zoomOut(zoomOut);

      var geoID = metro.properties.id;
      d3.select("input[name='wof_id']").attr("value",geoID);
      d3.select("input[name='wof_name']").attr("value",metro.properties.label);

      requestBoundingBox = this.calculateNewBox(metro.bbox);

      this.drawRequestBox();

      if (metro.geometry.type == "Feature")
        d3.json("wof/"+geoID+".geojson",function(data){
          outline = L.geoJson(data.geometry, { className : "outline" }).addTo(displayMap);
          displayMap.addLayer(outline);
        });

      var bbox = metro.bbox,
        p1 = L.latLng(bbox[1],bbox[0]),
        p2 = L.latLng(bbox[3],bbox[2]);
      var encompassed = [{
        country : "Encompassing Metros",
        metros : []
      }];
      extractLayers.forEach(function(l){
        if (l.getBounds().contains(p1) && l.getBounds().contains(p2))
          encompassed[0].metros.push({
            name : l.feature.properties.display_name,
            href : l.feature.properties.href,
            country : l.feature.properties.name.split("_")[1],
            bbox : l.feature.bbox
          })
      });

      var requestDiv = d3.select("#request-wrapper");

      requestDiv.select("#make-request")
        .style("display","block")
        .selectAll(".name").text(metro.properties.name);

      if (encompassed[0].metros.length){
        requestDiv.attr("class","encompassed");
        this.drawList(encompassed, geoID, metro.properties.name);
        return;
      }

      var biggestDist = Math.max(requestBoundingBox[1][1] - requestBoundingBox[0][1], requestBoundingBox[1][0] - requestBoundingBox[0][0]);
      if (biggestDist > 5)
        requestDiv.attr("class","request-greater-5");
      else if (biggestDist > 1)
        requestDiv.attr("class","request-greater-1");
      else
        requestDiv.attr("class","default");
    },
    clearMap : function() {
      if (rect) displayMap.removeLayer(rect);
      if (outline) displayMap.removeLayer(outline);
      dots.forEach(function(l){
        displayMap.removeLayer(l);
      });
      dots = [];
    },
    clearRequest : function() {
      this.clearMap();
      d3.select("#did-you-mean").style("display","none");
      d3.select("#make-request").style("display","none");
    },
    calculateOffset : function(theta, d, lat1, lng1) {
      var lat1 = lat1.toRad(),
        lng1 = lng1.toRad(),
        R = 6371;

      var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R)
            + Math.cos(lat1)*Math.sin(d/R)*Math.cos(theta) ),
        lng2 = lng1 + Math.atan2(Math.sin(theta)*Math.sin(d/R)*Math.cos(lat1),
              Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));

      return [lat2.toDeg(), lng2.toDeg()];
    },
    calculateNewBox : function(bbox) {
      var d = Math.sqrt(Math.pow(bbox[3]-bbox[1],2) + Math.pow(bbox[2]-bbox[0], 2))*25,
        distance = (d == 0) ? 10 : d,
        northEast = this.calculateOffset(-Math.PI*3/4, distance, bbox[1], bbox[0]),
        southWest = this.calculateOffset(Math.PI/4, distance, bbox[3], bbox[2]);
      return [northEast, southWest];
    },
    drawRequestBox : function() {
      this.clearMap();
      var m = this;
      rect = new L.Rectangle(new L.LatLngBounds(requestBoundingBox), { className : "blue" });
      displayMap.addLayer(rect);

      var myIcon = L.divIcon({className: 'drag-icon'});

      var cSW = new L.marker(requestBoundingBox[0], { icon : myIcon, draggable: true });
      dots.push(cSW);
      var cNE = new L.marker(requestBoundingBox[1], { icon : myIcon, draggable: true });
      dots.push(cNE);

      cSW.on("drag",function(e){
        requestBoundingBox[0] = [e.target.getLatLng().lat, e.target.getLatLng().lng];
        m.redrawBox();
      });
      cNE.on("drag",function(e){
        requestBoundingBox[1] = [e.target.getLatLng().lat, e.target.getLatLng().lng];
        m.redrawBox();
      });

      dots.forEach(function(l){
        displayMap.addLayer(l);
      });
      this.fillRequestForm();
    },
    redrawBox : function() {
      displayMap.removeLayer(rect);
      rect = new L.Rectangle(new L.LatLngBounds(requestBoundingBox), { className : "blue" });
      displayMap.addLayer(rect);
      this.fillRequestForm();
    },
    fillRequestForm : function() {
      d3.select("input[name='bbox_n']").attr("value",requestBoundingBox[1][0]);
      d3.select("input[name='bbox_w']").attr("value",requestBoundingBox[0][1]);
      d3.select("input[name='bbox_s']").attr("value",requestBoundingBox[0][0]);
      d3.select("input[name='bbox_e']").attr("value",requestBoundingBox[1][1]);
    }
  }
  return MetrosApp;
}<|endoftext|>


<commit_before>/**
 * @fileOverview Magic Search JS
 * @requires AngularJS
 *
 */
angular.module('MagicSearch', [])
    .directive('magicSearch', function($compile) {
        return {
            restrict: 'E',
            scope: {
                facets_json: '@facets',
                filter_keys: '=filterKeys',
                strings: '=strings'
            },
            templateUrl: function (scope, elem) {
                return elem.template;
            },
            controller: function ($scope, $timeout) {
                $scope.currentSearch = [];
                $scope.initSearch = function() {
                    // Parse facets JSON and convert to a list of facets.
                    $scope.facetsJson = $scope.facets_json.replace(/__apos__/g, "\'").replace(/__dquote__/g, '\\"').replace(/__bslash__/g, "\\");
                    $scope.facetsObj = JSON.parse($scope.facetsJson);
                    console.log("facets = "+$scope.facetsJson);
                    // set facets selected and remove them from facetsObj
                    var initialFacets = window.location.search;
                    if (initialFacets.indexOf('?') === 0) {
                        initialFacets = initialFacets.slice(1);
                    }
                    initialFacets = initialFacets.split('&');
                    if (initialFacets.length > 1 || initialFacets[0].length > 0) {
                        $timeout(function() {
                            $scope.strings['prompt'] = '';
                        });
                    }
                    angular.forEach(initialFacets, function(facet, idx) {
                        var facetParts = facet.split('=');
                        angular.forEach($scope.facetsObj, function(value, idx) {
                            if (value.name == facetParts[0]) {
                                if (value.options === undefined) {
                                    $scope.currentSearch.push({'name':facet, 'label':[value.label, facetParts[1]]});
                                    // allow free-form facets to remain
                                }
                                else {
                                    angular.forEach(value.options, function(option, idx) {
                                        if (option.key == facetParts[1]) {
                                            $scope.currentSearch.push({'name':facet, 'label':[value.label, option.label]});
                                            $scope.deleteFacetSelection(facetParts);
                                        }
                                    });
                                }
                            }
                        });
                    });
                    $scope.filteredObj = $scope.facetsObj;
                };
                // removes a facet from the menu
                $scope.deleteFacetSelection = function(facet_parts) {
                    angular.forEach($scope.facetsObj.slice(), function(facet, idx) {
                        if (facet.name == facet_parts[0]) {
                            if (facet.options === undefined) {
                                return;  // allow free-form facets to remain
                            }
                            for (var i=0; i<facet.options.length; i++) {
                                var option = facet.options[i];
                                if (option.key == facet_parts[1]) {
                                    $scope.facetsObj[idx].options.splice($scope.facetsObj[idx].options.indexOf(option), 1);
                                }
                            }
                            if (facet.options.length === 0) {
                                $scope.facetsObj.splice($scope.facetsObj.indexOf(facet), 1);
                            }
                        }
                    });
                };
                $('#search-input').on('keydown', function($event) {  // handle ctrl-char input
                    var key = $event.keyCode || $event.charCode;
                    if (key == 9) {  // prevent default when we can.
                        $event.preventDefault();
                    }
                });
                $('#search-input').on('keyup', function($event) {  // handle ctrl-char input
                    if ($event.metaKey == true) {
                        return;
                    }
                    var search_val = $('#search-input').val();
                    var key = $event.keyCode || $event.charCode;
                    if (key == 9) {  // tab, so select facet if narrowed down to 1
                        if ($scope.facetSelected === undefined) {
                            if ($scope.filteredObj.length != 1) return;
                            $scope.facetClicked(0, '', $scope.filteredObj[0].name);
                        }
                        else {
                            if ($scope.filteredOptions.length != 1) return;
                            $scope.optionClicked(0, '', $scope.filteredOptions[0].key);
                            $scope.resetState();
                        }
                        $timeout(function() {
                            $('#search-input').val('');
                        });
                        return;
                    }
                    if (key == 27) {  // esc, so cancel and reset everthing
                        $timeout(function() {
                            $scope.hideMenu();
                            $('#search-input').val('');
                        });
                        $scope.resetState();
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                        return;
                    }
                    if (key == 13) {  // enter, so accept value
                        // if tag search, treat as regular facet
                        if ($scope.facetSelected && $scope.facetSelected.options === undefined) {
                            var curr = $scope.facetSelected;
                            curr.name = curr.name + '=' + search_val;
                            curr.label[1] = search_val;
                            $scope.currentSearch.push(curr);
                            $scope.resetState();
                            $scope.emitQuery();
                            $scope.showMenu();
                        }
                        // if text search treat as search
                        else {
                            for (i=0; i<$scope.currentSearch.length; i++) {
                                if ($scope.currentSearch[i].name.indexOf('text') === 0) {
                                    $scope.currentSearch.splice(i, 1);
                                }
                            }
                            $scope.currentSearch.push({'name':'text='+search_val, 'label':['text', search_val]});
                            $scope.$apply();
                            $scope.hideMenu();
                            $('#search-input').val('');
                            $scope.$emit('textSearch', search_val, $scope.filter_keys);
                        }
                        $scope.filteredObj = $scope.facetsObj;
                    }
                    else {
                        if (search_val === '') {
                            $scope.filteredObj = $scope.facetsObj;
                            $scope.$emit('textSearch', '', $scope.filter_keys);
                        }
                        else {
                            $scope.filterFacets(search_val);
                        }
                    }
                });
                $('#search-input').on('keypress', function($event) {  // handle character input
                    var search_val = $('#search-input').val();
                    var key = $event.which || $event.keyCode || $event.charCode;
                    if (key != 8 && key != 46 && key != 13 && key != 9 && key != 27) {
                        search_val = search_val + String.fromCharCode(key).toLowerCase();
                    }
                    if (search_val == ' ') {  // space and field is empty, show menu
                        $scope.showMenu();
                        $timeout(function() {
                            $('#search-input').val('');
                        });
                        return;
                    }
                    if (search_val === '') {
                        $scope.filteredObj = $scope.facetsObj;
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                        return;
                    }
                    if (key != 8 && key != 46) {
                        $scope.filterFacets(search_val);
                    }
                });
                $scope.filterFacets = function(search_val) {
                    // try filtering facets/options.. if no facets match, do text search
                    var i, idx, label;
                    var filtered = [];
                    if ($scope.facetSelected === undefined) {
                        $scope.filteredObj = $scope.facetsObj;
                        for (i=0; i<$scope.filteredObj.length; i++) {
                            var facet = $scope.filteredObj[i];
                            idx = facet.label.toLowerCase().indexOf(search_val);
                            if (idx > -1) {
                                label = [facet.label.substring(0, idx), facet.label.substring(idx, idx + search_val.length), facet.label.substring(idx + search_val.length)];
                                filtered.push({'name':facet.name, 'label':label, 'options':facet.options});
                            }
                        }
                        if (filtered.length > 0) {
                            $scope.showMenu();
                            $timeout(function() {
                                $scope.filteredObj = filtered;
                            }, 0.1);
                        }
                        else {
                            $scope.$emit('textSearch', search_val, $scope.filter_keys);
                            $scope.hideMenu();
                        }
                    }
                    else {  // assume option search
                        $scope.filteredOptions = $scope.facetOptions;
                        if ($scope.facetOptions === undefined) { // no options, assume free form text facet
                            return;
                        }
                        for (i=0; i<$scope.filteredOptions.length; i++) {
                            var option = $scope.filteredOptions[i];
                            idx = option.label.toLowerCase().indexOf(search_val);
                            if (idx > -1) {
                                label = [option.label.substring(0, idx), option.label.substring(idx, idx + search_val.length), option.label.substring(idx + search_val.length)];
                                filtered.push({'key':option.key, 'label':label});
                            }
                        }
                        if (filtered.length > 0) {
                            $scope.showMenu();
                            $timeout(function() {
                                $scope.filteredOptions = filtered;
                            }, 0.1);
                        }
                    }
                };
                // enable text entry when mouse clicked anywhere in search box
                $('#search-main-area').on("click", function($event) {
                    $('#search-input').trigger("focus");
                    if ($scope.facetSelected === undefined) {
                        $scope.showMenu();
                    }
                });
                // when facet clicked, add 1st part of facet and set up options
                $scope.facetClicked = function($index, $event, name) {
                    $scope.hideMenu();
                    var facet = $scope.filteredObj[$index];
                    var label = facet.label;
                    if (Array.isArray(label)) {
                        label = label.join('');
                    }
                    $scope.facetSelected = {'name':facet.name, 'label':[label, '']};
                    if (facet.options !== undefined) {
                        $scope.filteredOptions = $scope.facetOptions = facet.options;
                        $scope.showMenu();
                    }
                    $timeout(function() {
                        $('#search-input').val('');
                    });
                    $scope.strings['prompt'] = '';
                    $timeout(function() {
                        $('#search-input').focus();
                    });
                };
                // when option clicked, complete facet and send event
                $scope.optionClicked = function($index, $event, name) {
                    $scope.hideMenu();
                    var curr = $scope.facetSelected;
                    curr.name = curr.name + '=' + name;
                    curr.label[1] = $scope.filteredOptions[$index].label;
                    if (Array.isArray(curr.label[1])) {
                        curr.label[1] = curr.label[1].join('');
                    }
                    $scope.currentSearch.push(curr);
                    $scope.resetState();
                    $scope.emitQuery();
                    $scope.showMenu();
                };
                // send event with new query string
                $scope.emitQuery = function(removed) {
                    var query = '';
                    for (var i=0; i<$scope.currentSearch.length; i++) {
                        if ($scope.currentSearch[i].name.indexOf('text') !== 0) {
                            if (query.length > 0) query = query + "&";
                            query = query + $scope.currentSearch[i].name;
                        }
                    }
                    if (removed !== undefined && removed.indexOf('text') === 0) {
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                    }
                    else {
                        $scope.$emit('searchUpdated', query);
                        if ($scope.currentSearch.length > 0) {
                            var newFacet = $scope.currentSearch[$scope.currentSearch.length-1].name;
                            $scope.deleteFacetSelection(newFacet.split('='));
                        }
                    }
                };
                // remove facet and either update filter or search
                $scope.removeFacet = function($index, $event) {
                    var removed = $scope.currentSearch[$index].name;
                    $scope.currentSearch.splice($index, 1);
                    if ($scope.facetSelected === undefined) {
                        $scope.emitQuery(removed);
                    }
                    else {
                        $scope.resetState();
                        $('#search-input').val('');
                    }
                    // facet re-enabled by reload
                };
                // clear entire searchbar
                $scope.clearSearch = function() {
                    if ($scope.currentSearch.length > 0) {
                        $scope.currentSearch = [];
                        $scope.facetsObj = JSON.parse($scope.facetsJson);
                        $scope.resetState();
                        $scope.$emit('searchUpdated', '');
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                    }
                };
                $scope.isMatchLabel = function(label) {
                    return Array.isArray(label);
                };
                $scope.resetState = function() {
                    $('#search-input').val('');
                    $scope.filteredObj = $scope.facetsObj;
                    $scope.facetSelected = undefined;
                    $scope.facetOptions = undefined;
                    $scope.filteredOptions = undefined
                };
                // showMenu and hideMenu depend on foundation's dropdown. They need
                // to be modified to work with another dropdown implemenation (i.e. bootstrap)
                $scope.showMenu = function() {
                    $timeout(function() {
                        if ($('#facet-drop').hasClass('open') === false) {
                            $('#search-input').trigger('click');
                        }
                    });
                };
                $scope.hideMenu = function() {
                    $(document).foundation('dropdown', 'closeall');
                };
                $scope.initSearch();
            }
        };
    })
;
<commit_msg>removed debug<commit_after>/**
 * @fileOverview Magic Search JS
 * @requires AngularJS
 *
 */
angular.module('MagicSearch', [])
    .directive('magicSearch', function($compile) {
        return {
            restrict: 'E',
            scope: {
                facets_json: '@facets',
                filter_keys: '=filterKeys',
                strings: '=strings'
            },
            templateUrl: function (scope, elem) {
                return elem.template;
            },
            controller: function ($scope, $timeout) {
                $scope.currentSearch = [];
                $scope.initSearch = function() {
                    // Parse facets JSON and convert to a list of facets.
                    $scope.facetsJson = $scope.facets_json.replace(/__apos__/g, "\'").replace(/__dquote__/g, '\\"').replace(/__bslash__/g, "\\");
                    $scope.facetsObj = JSON.parse($scope.facetsJson);
                    // set facets selected and remove them from facetsObj
                    var initialFacets = window.location.search;
                    if (initialFacets.indexOf('?') === 0) {
                        initialFacets = initialFacets.slice(1);
                    }
                    initialFacets = initialFacets.split('&');
                    if (initialFacets.length > 1 || initialFacets[0].length > 0) {
                        $timeout(function() {
                            $scope.strings['prompt'] = '';
                        });
                    }
                    angular.forEach(initialFacets, function(facet, idx) {
                        var facetParts = facet.split('=');
                        angular.forEach($scope.facetsObj, function(value, idx) {
                            if (value.name == facetParts[0]) {
                                if (value.options === undefined) {
                                    $scope.currentSearch.push({'name':facet, 'label':[value.label, facetParts[1]]});
                                    // allow free-form facets to remain
                                }
                                else {
                                    angular.forEach(value.options, function(option, idx) {
                                        if (option.key == facetParts[1]) {
                                            $scope.currentSearch.push({'name':facet, 'label':[value.label, option.label]});
                                            $scope.deleteFacetSelection(facetParts);
                                        }
                                    });
                                }
                            }
                        });
                    });
                    $scope.filteredObj = $scope.facetsObj;
                };
                // removes a facet from the menu
                $scope.deleteFacetSelection = function(facet_parts) {
                    angular.forEach($scope.facetsObj.slice(), function(facet, idx) {
                        if (facet.name == facet_parts[0]) {
                            if (facet.options === undefined) {
                                return;  // allow free-form facets to remain
                            }
                            for (var i=0; i<facet.options.length; i++) {
                                var option = facet.options[i];
                                if (option.key == facet_parts[1]) {
                                    $scope.facetsObj[idx].options.splice($scope.facetsObj[idx].options.indexOf(option), 1);
                                }
                            }
                            if (facet.options.length === 0) {
                                $scope.facetsObj.splice($scope.facetsObj.indexOf(facet), 1);
                            }
                        }
                    });
                };
                $('#search-input').on('keydown', function($event) {  // handle ctrl-char input
                    var key = $event.keyCode || $event.charCode;
                    if (key == 9) {  // prevent default when we can.
                        $event.preventDefault();
                    }
                });
                $('#search-input').on('keyup', function($event) {  // handle ctrl-char input
                    if ($event.metaKey == true) {
                        return;
                    }
                    var search_val = $('#search-input').val();
                    var key = $event.keyCode || $event.charCode;
                    if (key == 9) {  // tab, so select facet if narrowed down to 1
                        if ($scope.facetSelected === undefined) {
                            if ($scope.filteredObj.length != 1) return;
                            $scope.facetClicked(0, '', $scope.filteredObj[0].name);
                        }
                        else {
                            if ($scope.filteredOptions.length != 1) return;
                            $scope.optionClicked(0, '', $scope.filteredOptions[0].key);
                            $scope.resetState();
                        }
                        $timeout(function() {
                            $('#search-input').val('');
                        });
                        return;
                    }
                    if (key == 27) {  // esc, so cancel and reset everthing
                        $timeout(function() {
                            $scope.hideMenu();
                            $('#search-input').val('');
                        });
                        $scope.resetState();
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                        return;
                    }
                    if (key == 13) {  // enter, so accept value
                        // if tag search, treat as regular facet
                        if ($scope.facetSelected && $scope.facetSelected.options === undefined) {
                            var curr = $scope.facetSelected;
                            curr.name = curr.name + '=' + search_val;
                            curr.label[1] = search_val;
                            $scope.currentSearch.push(curr);
                            $scope.resetState();
                            $scope.emitQuery();
                            $scope.showMenu();
                        }
                        // if text search treat as search
                        else {
                            for (i=0; i<$scope.currentSearch.length; i++) {
                                if ($scope.currentSearch[i].name.indexOf('text') === 0) {
                                    $scope.currentSearch.splice(i, 1);
                                }
                            }
                            $scope.currentSearch.push({'name':'text='+search_val, 'label':['text', search_val]});
                            $scope.$apply();
                            $scope.hideMenu();
                            $('#search-input').val('');
                            $scope.$emit('textSearch', search_val, $scope.filter_keys);
                        }
                        $scope.filteredObj = $scope.facetsObj;
                    }
                    else {
                        if (search_val === '') {
                            $scope.filteredObj = $scope.facetsObj;
                            $scope.$emit('textSearch', '', $scope.filter_keys);
                        }
                        else {
                            $scope.filterFacets(search_val);
                        }
                    }
                });
                $('#search-input').on('keypress', function($event) {  // handle character input
                    var search_val = $('#search-input').val();
                    var key = $event.which || $event.keyCode || $event.charCode;
                    if (key != 8 && key != 46 && key != 13 && key != 9 && key != 27) {
                        search_val = search_val + String.fromCharCode(key).toLowerCase();
                    }
                    if (search_val == ' ') {  // space and field is empty, show menu
                        $scope.showMenu();
                        $timeout(function() {
                            $('#search-input').val('');
                        });
                        return;
                    }
                    if (search_val === '') {
                        $scope.filteredObj = $scope.facetsObj;
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                        return;
                    }
                    if (key != 8 && key != 46) {
                        $scope.filterFacets(search_val);
                    }
                });
                $scope.filterFacets = function(search_val) {
                    // try filtering facets/options.. if no facets match, do text search
                    var i, idx, label;
                    var filtered = [];
                    if ($scope.facetSelected === undefined) {
                        $scope.filteredObj = $scope.facetsObj;
                        for (i=0; i<$scope.filteredObj.length; i++) {
                            var facet = $scope.filteredObj[i];
                            idx = facet.label.toLowerCase().indexOf(search_val);
                            if (idx > -1) {
                                label = [facet.label.substring(0, idx), facet.label.substring(idx, idx + search_val.length), facet.label.substring(idx + search_val.length)];
                                filtered.push({'name':facet.name, 'label':label, 'options':facet.options});
                            }
                        }
                        if (filtered.length > 0) {
                            $scope.showMenu();
                            $timeout(function() {
                                $scope.filteredObj = filtered;
                            }, 0.1);
                        }
                        else {
                            $scope.$emit('textSearch', search_val, $scope.filter_keys);
                            $scope.hideMenu();
                        }
                    }
                    else {  // assume option search
                        $scope.filteredOptions = $scope.facetOptions;
                        if ($scope.facetOptions === undefined) { // no options, assume free form text facet
                            return;
                        }
                        for (i=0; i<$scope.filteredOptions.length; i++) {
                            var option = $scope.filteredOptions[i];
                            idx = option.label.toLowerCase().indexOf(search_val);
                            if (idx > -1) {
                                label = [option.label.substring(0, idx), option.label.substring(idx, idx + search_val.length), option.label.substring(idx + search_val.length)];
                                filtered.push({'key':option.key, 'label':label});
                            }
                        }
                        if (filtered.length > 0) {
                            $scope.showMenu();
                            $timeout(function() {
                                $scope.filteredOptions = filtered;
                            }, 0.1);
                        }
                    }
                };
                // enable text entry when mouse clicked anywhere in search box
                $('#search-main-area').on("click", function($event) {
                    $('#search-input').trigger("focus");
                    if ($scope.facetSelected === undefined) {
                        $scope.showMenu();
                    }
                });
                // when facet clicked, add 1st part of facet and set up options
                $scope.facetClicked = function($index, $event, name) {
                    $scope.hideMenu();
                    var facet = $scope.filteredObj[$index];
                    var label = facet.label;
                    if (Array.isArray(label)) {
                        label = label.join('');
                    }
                    $scope.facetSelected = {'name':facet.name, 'label':[label, '']};
                    if (facet.options !== undefined) {
                        $scope.filteredOptions = $scope.facetOptions = facet.options;
                        $scope.showMenu();
                    }
                    $timeout(function() {
                        $('#search-input').val('');
                    });
                    $scope.strings['prompt'] = '';
                    $timeout(function() {
                        $('#search-input').focus();
                    });
                };
                // when option clicked, complete facet and send event
                $scope.optionClicked = function($index, $event, name) {
                    $scope.hideMenu();
                    var curr = $scope.facetSelected;
                    curr.name = curr.name + '=' + name;
                    curr.label[1] = $scope.filteredOptions[$index].label;
                    if (Array.isArray(curr.label[1])) {
                        curr.label[1] = curr.label[1].join('');
                    }
                    $scope.currentSearch.push(curr);
                    $scope.resetState();
                    $scope.emitQuery();
                    $scope.showMenu();
                };
                // send event with new query string
                $scope.emitQuery = function(removed) {
                    var query = '';
                    for (var i=0; i<$scope.currentSearch.length; i++) {
                        if ($scope.currentSearch[i].name.indexOf('text') !== 0) {
                            if (query.length > 0) query = query + "&";
                            query = query + $scope.currentSearch[i].name;
                        }
                    }
                    if (removed !== undefined && removed.indexOf('text') === 0) {
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                    }
                    else {
                        $scope.$emit('searchUpdated', query);
                        if ($scope.currentSearch.length > 0) {
                            var newFacet = $scope.currentSearch[$scope.currentSearch.length-1].name;
                            $scope.deleteFacetSelection(newFacet.split('='));
                        }
                    }
                };
                // remove facet and either update filter or search
                $scope.removeFacet = function($index, $event) {
                    var removed = $scope.currentSearch[$index].name;
                    $scope.currentSearch.splice($index, 1);
                    if ($scope.facetSelected === undefined) {
                        $scope.emitQuery(removed);
                    }
                    else {
                        $scope.resetState();
                        $('#search-input').val('');
                    }
                    // facet re-enabled by reload
                };
                // clear entire searchbar
                $scope.clearSearch = function() {
                    if ($scope.currentSearch.length > 0) {
                        $scope.currentSearch = [];
                        $scope.facetsObj = JSON.parse($scope.facetsJson);
                        $scope.resetState();
                        $scope.$emit('searchUpdated', '');
                        $scope.$emit('textSearch', '', $scope.filter_keys);
                    }
                };
                $scope.isMatchLabel = function(label) {
                    return Array.isArray(label);
                };
                $scope.resetState = function() {
                    $('#search-input').val('');
                    $scope.filteredObj = $scope.facetsObj;
                    $scope.facetSelected = undefined;
                    $scope.facetOptions = undefined;
                    $scope.filteredOptions = undefined
                };
                // showMenu and hideMenu depend on foundation's dropdown. They need
                // to be modified to work with another dropdown implemenation (i.e. bootstrap)
                $scope.showMenu = function() {
                    $timeout(function() {
                        if ($('#facet-drop').hasClass('open') === false) {
                            $('#search-input').trigger('click');
                        }
                    });
                };
                $scope.hideMenu = function() {
                    $(document).foundation('dropdown', 'closeall');
                };
                $scope.initSearch();
            }
        };
    })
;
<|endoftext|>


<commit_before>(function(global, factory) {
  'use strict';
  global.fcm = new factory(global, global.document)();
})(typeof window !== 'undefined' ? window : this, function(w, d) {
  var fcm = function() {
    var self = this;

    function createFirebaseToken() {
    }

    function deleteFirebaseToken() {
    }

    function requestPushPermission() {
    }

    /**
     * Register firebase push
     */
    self.register = function() {
    };

    /**
     * Unregister firebase push
     */
    self.unregister = function() {
    };
  };
  return fcm;
});

<commit_msg>Request permission to create FCM token and send it to server (#67)<commit_after>(function(global, factory) {
  'use strict';
  global.fcm = new factory(global, global.document)();
})(typeof window !== 'undefined' ? window : this, function(w, d) {
  var fcm = function() {
    var self = this;
    var authorizationKey = '';
    var clientToken = '';

    var config = {
      apiKey: '',
      authDomain: '',
      databaseURL: '',
      storageBucket: '',
      messagingSenderId: ''
    };

    firebase.initializeApp(config);
    const messaging = firebase.messaging();

    function createFirebaseToken() {
      messaging.getToken()
      .then(function(token) {
        if (token) {
          clientToken = token;
          sendFCMTokenToServer();
        } else {
          console.log('No token available.');
        }
      })
      .catch(function(err) {
        console.log('An error occurred while retrieving token. err : ', err);
      });
    }

    function deleteFirebaseToken() {
    }

    function requestPushPermission() {
      messaging.requestPermission()
      .then(function() {
        createFirebaseToken();
      })
      .catch(function(err) {
        console.log('Notification permission denied. err : ', err);
      });
    }

    function sendFCMTokenToServer() {
      var http = new XMLHttpRequest();
      var url = "https://localhost:9443/api/client";
      http.open("POST", url, true);
      http.setRequestHeader("Content-Type", "application/json");
      http.setRequestHeader("Authorization", "key=",authorizationKey);
      http.onreadystatechange = function() {
        if (http.readyState == XMLHttpRequest.DONE && http.status == 200) {
          console.log(http.responseText);
        }
      }
      http.send(JSON.stringify({
        to: clientToken
      }));
    }

    /**
     * Register firebase push
     */
    self.register = function() {
      requestPushPermission();
    };

    /**
     * Unregister firebase push
     */
    self.unregister = function() {
    };
  };
  return fcm;
});

<|endoftext|>


<commit_before>import Validation from "../util/Validation";
/**
 * Resrictions to constrain the results to be retrieved.
 */
class Restrictions {

    /**
     * evulates op and execute it.
     * @param {string} op
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    op(op: string, key: string, value: any): Function {
        return (data: Map): boolean => {
            if (typeof data[key] === "number") {
                return eval(data[key]+ op + value);
            }
            return eval("'" + data[key] + "'" + op + "'" +value + "'");
        };
    }

    /**
     * checks equality given value and given value of data by key.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @return {Function}
     * @private
     */
    __eq(key: string, value: any, caseSensitive: boolean): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            if (propValue && typeof propValue !== "string") {
                propValue = propValue.toString();
            }
            if (value && typeof value !== "string") {
                value = value.toString();
            }
            if (!caseSensitive) {
                if(value) {
                    value = value.toLocaleLowerCase();
                }
                if(propValue){
                    propValue = propValue.toLocaleLowerCase();
                }
            }
            return propValue === value;
        };
    }

    /**
     * checks equality given value and given value of data by key.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @return {Function}
     */
    eq(key: string, value: any, caseSensitive: boolean): Function {
        return this.__eq(key, value, caseSensitive);
    }

    /**
     * checks given value of data by key less then given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    lt(key: string, value: any): Function {
        return (data: Map): boolean => {
            return data[key] < value;
        };
    };

    /**
     * checks given value of data by key less then or equals given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    lte(key: string, value: any): Function {
        return (data: Map): boolean => {
            /* eslint-disable eqeqeq */
            console.log(data[key]);
            console.log(value);
            return data[key] <= value;
        };
    };

    /**
     * checks given value of data by key greater then given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    gt(key: string, value: any): Function {
        return (data: Map): boolean => {
            return data[key] > value;
        };
    };

    /**
     * checks given value of data by key greater then or equals given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    gte(key: string, value: any): Function {
        return (data: Map): boolean => {
            return data[key] >= value;
        };
    };

    /**
     * checks given value of data by key between given startValue and given endValue.
     * @param {string} key
     * @param {any} startValue
     * @param {any} endValue
     * @return {Function}
     */
    between(key: string, startValue: any, endValue: any): Function{
        if(startValue > endValue) {
            let temp = startValue;
            startValue = endValue;
            endValue = temp;
        }
        let funcArray = [this.gte(key, startValue), this.lte(key, endValue)];
        return this.and.apply(this, funcArray);
    }

    /**
     * checks given value of data by key like given value by  fromLeft and fromRight parameters.
     * @param {string} key
     * @param {any} value
     * @param {boolean} fromLeft
     * @param {boolean} fromRight
     * @param {boolean} caseSensitive
     * @returns {Function}
     * @private
     */
    __like(key: string, value: any, fromLeft: boolean, fromRight: boolean, caseSensitive: boolean): Function{
        return (data: Map): boolean => {
            let propValue = data[key];
            if (propValue && typeof propValue !== "string") {
                propValue = propValue.toString();
            }
            if (!caseSensitive) {
                value = value.toLocaleLowerCase();
                propValue = propValue.toLocaleLowerCase();
            }

            if (fromLeft && fromRight) {
                return propValue.indexOf(value) > -1;
            } else if (fromLeft) {
                return Validation.startsWith(propValue, value);
            } else if (fromRight) {
                return Validation.endsWith(propValue, value);
            } else {
                return this.__eq(key, value, caseSensitive)(data);
            }

        };
    }

    /**
     * checks given value of data by key like given value by percent (%) charachter like sql `like`.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     * @private
     */
    __likeWithPercent(key: string, value: any, caseSensitive: boolean): Function{
        let fromLeft = Validation.endsWith(value, "%");
        let fromRight = Validation.startsWith(value, "%");
        let startIndex = fromRight ? 1 : 0;
        let endIndex = fromLeft ? value.length - 1 : value.length;
        value = value.substring(startIndex, endIndex);
        return this.__like(key, value, fromLeft, fromRight, caseSensitive);
    }

    /**
     * checks given value of data by key startsWith given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    startsWith(key: string, value: any, caseSensitive: boolean): Function {
        return this.__like(key, value, true, false, caseSensitive);
    }

    /**
     * checks given value of data by key endsWith given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    endsWith(key: string, value: any, caseSensitive: boolean): Function {
        return this.__like(key, value, false, true, caseSensitive);
    }

    /**
     * checks given value of data by key contains given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    contains(key: string, value: any, caseSensitive: boolean): Function {
        return this.__like(key, value, true, true, caseSensitive);
    }

    /**
     * checks given value of data by key like given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    like(key: string, value: any, caseSensitive: boolean): Function {
        return this.__likeWithPercent(key, value, caseSensitive);
    };

    /**
     *
     * @param {string} key
     * @param {Array<any>} values
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    /**
     * checks given value of data by key in given array values by caseSensitive parameter.
     * @param {string} key
     * @param {Array<any>} values
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    in(key: string, values: Array<any>, caseSensitive: boolean) : Function {
        let restrictions = [];
        for (let i = 0; i < values.length; i++) {
            restrictions[restrictions.length] = this.eq(key, values[i], caseSensitive);
        }
        return this.or.apply(this, restrictions);
    }

    /**
     *
     * @param {string} key
     * @returns {Function}
     */
    isNull(key: string): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            return (propValue === undefined || propValue === null);
        };
    }

    /**
     *
     * @param {string} key
     * @returns {Function}
     */
    isNotNull(key: string): Function {
        return (data: Map): boolean => {
            return !(data[key] === undefined || data[key] === null);
        };
    }

    /**
     *
     * @param {string} key
     * @returns {Function}
     */
    isEmpty(key: string): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            return (propValue === undefined || propValue === null) || propValue === "";
        };
    }

    /**
     *
     * @param {string} key
     * @returns {Function}
     */
    isNotEmpty(key: string): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            return !((propValue === undefined || propValue === null) || propValue === "");
        };
    }

    /**
     *
     * @param { ...Function }restrictions
     * @returns {Function}
     */
    or(...restrictions: Array<Function>): Function {
        return (data: Map): boolean => {
            let result = false;
            for (let i = 0; i < restrictions.length; i++) {
                result = result || restrictions[i](data);
            }
            return result;
        };
    }

    /**
     *
     * @param { ...Function }restrictions
     * @returns {Function}
     */
    and (...restrictions: Array<Function>): Function {
        return (data: Map): boolean => {

            let result = true;
            for (let i = 0; i < restrictions.length; i++) {
                result = result && restrictions[i](data);
            }

            return result;
        };
    }

}

export default new Restrictions();
<commit_msg>- added descriptions.<commit_after>import Validation from "../util/Validation";
/**
 * Resrictions to constrain the results to be retrieved.
 */
class Restrictions {

    /**
     * @description evulates op and execute it.
     * @param {string} op
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    op(op: string, key: string, value: any): Function {
        return (data: Map): boolean => {
            if (typeof data[key] === "number") {
                return eval(data[key]+ op + value);
            }
            return eval("'" + data[key] + "'" + op + "'" +value + "'");
        };
    }

    /**
     * @description checks equality given value and given value of data by key.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @return {Function}
     * @private
     */
    __eq(key: string, value: any, caseSensitive: boolean): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            if (propValue && typeof propValue !== "string") {
                propValue = propValue.toString();
            }
            if (value && typeof value !== "string") {
                value = value.toString();
            }
            if (!caseSensitive) {
                if(value) {
                    value = value.toLocaleLowerCase();
                }
                if(propValue){
                    propValue = propValue.toLocaleLowerCase();
                }
            }
            return propValue === value;
        };
    }

    /**
     * @description checks equality given value and given value of data by key.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @return {Function}
     */
    eq(key: string, value: any, caseSensitive: boolean): Function {
        return this.__eq(key, value, caseSensitive);
    }

    /**
     * @description checks given value of data by key less then given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    lt(key: string, value: any): Function {
        return (data: Map): boolean => {
            return data[key] < value;
        };
    };

    /**
     * @description checks given value of data by key less then or equals given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    lte(key: string, value: any): Function {
        return (data: Map): boolean => {
            /* eslint-disable eqeqeq */
            console.log(data[key]);
            console.log(value);
            return data[key] <= value;
        };
    };

    /**
     * @description checks given value of data by key greater then given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    gt(key: string, value: any): Function {
        return (data: Map): boolean => {
            return data[key] > value;
        };
    };

    /**
     * @description checks given value of data by key greater then or equals given value .
     * @param {string} key
     * @param {any} value
     * @return {Function}
     */
    gte(key: string, value: any): Function {
        return (data: Map): boolean => {
            return data[key] >= value;
        };
    };

    /**
     * @description checks given value of data by key between given startValue and given endValue.
     * @param {string} key
     * @param {any} startValue
     * @param {any} endValue
     * @return {Function}
     */
    between(key: string, startValue: any, endValue: any): Function{
        if(startValue > endValue) {
            let temp = startValue;
            startValue = endValue;
            endValue = temp;
        }
        let funcArray = [this.gte(key, startValue), this.lte(key, endValue)];
        return this.and.apply(this, funcArray);
    }

    /**
     * @description checks given value of data by key like given value by  fromLeft and fromRight parameters.
     * @param {string} key
     * @param {any} value
     * @param {boolean} fromLeft
     * @param {boolean} fromRight
     * @param {boolean} caseSensitive
     * @returns {Function}
     * @private
     */
    __like(key: string, value: any, fromLeft: boolean, fromRight: boolean, caseSensitive: boolean): Function{
        return (data: Map): boolean => {
            let propValue = data[key];
            if (propValue && typeof propValue !== "string") {
                propValue = propValue.toString();
            }
            if (!caseSensitive) {
                value = value.toLocaleLowerCase();
                propValue = propValue.toLocaleLowerCase();
            }

            if (fromLeft && fromRight) {
                return propValue.indexOf(value) > -1;
            } else if (fromLeft) {
                return Validation.startsWith(propValue, value);
            } else if (fromRight) {
                return Validation.endsWith(propValue, value);
            } else {
                return this.__eq(key, value, caseSensitive)(data);
            }

        };
    }

    /**
     * @description checks given value of data by key like given value by percent (%) charachter like sql `like`.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     * @private
     */
    __likeWithPercent(key: string, value: any, caseSensitive: boolean): Function{
        let fromLeft = Validation.endsWith(value, "%");
        let fromRight = Validation.startsWith(value, "%");
        let startIndex = fromRight ? 1 : 0;
        let endIndex = fromLeft ? value.length - 1 : value.length;
        value = value.substring(startIndex, endIndex);
        return this.__like(key, value, fromLeft, fromRight, caseSensitive);
    }

    /**
     * @description checks given value of data by key startsWith given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    startsWith(key: string, value: any, caseSensitive: boolean): Function {
        return this.__like(key, value, true, false, caseSensitive);
    }

    /**
     * @description checks given value of data by key endsWith given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    endsWith(key: string, value: any, caseSensitive: boolean): Function {
        return this.__like(key, value, false, true, caseSensitive);
    }

    /**
     * @description checks given value of data by key contains given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    contains(key: string, value: any, caseSensitive: boolean): Function {
        return this.__like(key, value, true, true, caseSensitive);
    }

    /**
     * @description checks given value of data by key like given value by caseSensitive parameter.
     * @param {string} key
     * @param {any} value
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    like(key: string, value: any, caseSensitive: boolean): Function {
        return this.__likeWithPercent(key, value, caseSensitive);
    };

    /**
     *
     * @description @param {string} key
     * @param {Array<any>} values
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    /**
     * @description checks given value of data by key in given array values by caseSensitive parameter.
     * @param {string} key
     * @param {Array<any>} values
     * @param {boolean} caseSensitive
     * @returns {Function}
     */
    in(key: string, values: Array<any>, caseSensitive: boolean) : Function {
        let restrictions = [];
        for (let i = 0; i < values.length; i++) {
            restrictions[restrictions.length] = this.eq(key, values[i], caseSensitive);
        }
        return this.or.apply(this, restrictions);
    }

    /**
     * @description checks given value of data by key is null.
     * @param {string} key
     * @returns {Function}
     */
    isNull(key: string): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            return (propValue === undefined || propValue === null);
        };
    }

    /**
     * @description checks given value of data by key is not null.
     * @param {string} key
     * @returns {Function}
     */
    isNotNull(key: string): Function {
        return (data: Map): boolean => {
            return !(data[key] === undefined || data[key] === null);
        };
    }

    /**
     * @description checks given value of data by key is empty.
     * @param {string} key
     * @returns {Function}
     */
    isEmpty(key: string): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            return (propValue === undefined || propValue === null) || propValue === "";
        };
    }

    /**
     * @description checks given value of data by key is not empty.
     * @param {string} key
     * @returns {Function}
     */
    isNotEmpty(key: string): Function {
        return (data: Map): boolean => {
            let propValue = data[key];
            return !((propValue === undefined || propValue === null) || propValue === "");
        };
    }

    /**
     * @description joins Restrictions functions with or validation.
     * @param { ...Function }restrictions
     * @returns {Function}
     */
    or(...restrictions: Array<Function>): Function {
        return (data: Map): boolean => {
            let result = false;
            for (let i = 0; i < restrictions.length; i++) {
                result = result || restrictions[i](data);
            }
            return result;
        };
    }

    /**
     * @description joins Restrictions functions with and validation.
     * @param { ...Function }restrictions
     * @returns {Function}
     */
    and (...restrictions: Array<Function>): Function {
        return (data: Map): boolean => {

            let result = true;
            for (let i = 0; i < restrictions.length; i++) {
                result = result && restrictions[i](data);
            }

            return result;
        };
    }

}

export default new Restrictions();
<|endoftext|>


<commit_before>'use strict';

angular.module('casusMIT3.results', ['ngRoute','AdalAngular'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/results', {
    templateUrl: 'results/results.html',
    controller: 'resultsCtrl',
    requireADLogin: true
  });
}])

.controller('resultsCtrl', ['$scope', 'powerBi',function($scope, powerBi) {

  $scope.dashboards;
  $scope.status;
    $scope.tile

listAllDashboards();
    getDashboardTile();

  function listAllDashboards(){
    powerBi.listAllDashboards()
        .then(function (response) {
          $scope.dashboards = response.data;

        },function (error) {
          $scope.status = "Unable to load Dashboard data: " + error.message;

        })
  }

    function getDashboardTile(){
        powerBi.getDashboardTile()
            .then(function (response) {
                $scope.tile = response.data;

            },function (error) {
                $scope.status = "Unable to load Dashboard data: " + error.message;

            })
    }

}]);<commit_msg>Changed connect details<commit_after>'use strict';

angular.module('casusMIT3.results', ['ngRoute','AdalAngular'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/results', {
    templateUrl: 'results/results.html',
    controller: 'resultsCtrl',
    requireADLogin: true
  });
}])

.controller('resultsCtrl', ['$scope', 'powerBi',function($scope, powerBi) {

  $scope.dashboards;
  $scope.status;
    $scope.tile;

listAllDashboards();
    getDashboardTile();

  function listAllDashboards(){
    powerBi.listAllDashboards()
        .then(function (response) {
          $scope.dashboards = response.data;

        },function (error) {
          $scope.status = "Unable to load Dashboard data: " + error.message;

        })
  }

    function getDashboardTile(){
        powerBi.getDashboardTile('a34b834a-8988-490e-ad29-3accf6270a98')
            .then(function (response) {
                $scope.tile = response.data;

            },function (error) {
                $scope.status = "Unable to load Dashboard data: " + error.message;

            })
    }

}]);<|endoftext|>