<commit_before>var _autoselects = [];
function autoselectInit() {
  var els = document.getElementsByClassName("form-autoselect");
  for (var i=0; i<els.length; i++) {
    if (!els[i].className.match("autoselect-init")) {
      els[i].addClass("autoselect-init");
      _autoselects.push(new autoselect(els[i]));
    }
  }
  if (typeof(MutationObserver) == "function") {
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        autoselectObserve(mutation.target);
      });
    });
    var config = { childList: true, subtree: true };
    observer.observe(document.body, config);
  }
  else {
    setInterval(function() {
      autoselectObserve(document.body);
    }, 1000);
  }
}
function autoselectObserve(el) {
  var els = el.getElementsByClassName("form-autoselect");
  for (var i=0; i<els.length; i++) {
    if (!els[i].className.match("autoselect-init")) {
      els[i].addClass("autoselect-init");
      _autoselects.push(new autoselect(els[i]));
    }
  }
}

function autoselect(el) {

  this.tags = {
    input: el
  };

  this.init = function() {
    var self = this;
    this.optionActive = -1;
    this.tags.item = formGetItem(this.tags.input);
    this.tags.select = this.tags.item.getElementsByTagName("select")[0];
    this.tags.options = this.tags.item.getElementsByClassName("autoselect-options")[0];
    this.tags.input.addEventListener("blur", function(){ self.onBlur(); }, false);
    this.tags.input.addEventListener("focus", function(){ self.onFocus(); }, false);
    this.tags.input.addEventListener("keydown", function(e){ self.onKeyDown(e); }, false);
    this.tags.input.addEventListener("keyup", function(e){ self.onKeyUp(e); }, false);
    this.tags.input.addClass("autoselect-init");
    self.selectChange();
    if (typeof(MutationObserver) == "function") {
      var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
          self.selectChange(mutation.target);
        });
      });
      var config = { childList: true, subtree: true };
      observer.observe(this.tags.select, config);
    }
  }

  this.selectChange = function() {
    if (this.isDisabled()) {
      this.tags.input.setAttribute("disabled", true);
      this.tags.item.addClass("disabled");
    }
    else {
      this.tags.input.removeAttribute("disabled");
      this.tags.item.removeClass("disabled");
    }
    this.renderOptions();
  }

  this.renderOptions = function() {
    var value = this.tags.input.value.toLowerCase();
    this.tags.options.innerHTML = "";
    this.tags.option = [];
    this.optionActive = -1;
    for (var i=0; i<this.tags.select.options.length; i++) {
      var match = false;
      var lower = this.tags.select.options[i].text.toLowerCase();
      if (!value.length || lower.indexOf(value) != -1) {
        match = true;
      }
      else {
        var arr = lower.split(" ");
        for (var j=0; j<arr.length; j++) {
          if (arr[j].substr(0, value.length) == value) {
            match = true;
            break;
          }
        }
      }
      if (match) {
        this.tags.option[i] = document.createElement("div");
        this.tags.option[i].className = "autoselect-option";
        this.tags.option[i].innerHTML = this.tags.select.options[i].text;
        this.tags.options.appendChild(this.tags.option[i]);
        (function(self, n) {
          self.tags.option[n].addEventListener("click", function(){ self.optionClick(n); }, false);
        }(this, i));
      }
    }
  }

  this.onFocus = function() {
    this.renderOptions();
    this.tags.input.select();
    var self = this;
    setTimeout(function(){
      self.tags.input.select();
    }, 100);
  }

  this.onBlur = function() {
    if (!this.tags.input.value.length && this.tags.select.selectedIndex != 0) {
      this.tags.select.selectedIndex = 0;
      this.tags.select.trigger("change");
    }
  }

  this.isDisabled = function() {
    return this.tags.select.getAttribute("disabled") !== null;
  }

  /*
    e.keyCode
      37 = left
      38 = up
      39 = right
      40 = down
      27 = esc
      13 = enter
  */
  this.onKeyDown = function(e) {
    var code = e.keyCode;
    if (code == 13) {
      e.preventDefault();
      return false;
    }
    else if (code == 27) {
      this.tags.input.blur();
    }
  }
  this.onKeyUp = function(e) {
    var code = e.keyCode;
    if (code == 13) {
      e.preventDefault();
      this.optionEnter();
      return false;
    }
    else if (code == 40 || code == 38) {
      if (code == 40)
        this.optionDown();
      else
        this.optionUp();
    }
    else {
      this.renderOptions();
    }
  }

  this.optionUp = function() {
    for (var i=this.optionActive-1; i >= 0; i--) {
      if (this.tags.option[i]) {
        if (this.optionActive != -1)
          this.tags.option[this.optionActive].removeClass("active");
        this.tags.option[i].addClass("active");
        this.optionActive = i;
        break;
      }
    }
  }
  this.optionDown = function() {
    for (var i=this.optionActive+1; i < this.tags.select.options.length; i++) {
      if (this.tags.option[i]) {
        if (this.optionActive != -1)
          this.tags.option[this.optionActive].removeClass("active");
        this.tags.option[i].addClass("active");
        this.optionActive = i;
        break;
      }
    }
  }
  this.optionEnter = function() {
    if (this.optionActive != -1)
      this.optionClick(this.optionActive);
  }

  this.optionClick = function(n) {
    this.tags.input.value = (this.tags.select.value.length ? this.tags.select.options[n].text : "");
    this.tags.input.blur();
    this.tags.select.selectedIndex = n;
    this.tags.select.trigger("change");
  }

  this.init();

}

window.addEventListener("load", autoselectInit, false);<commit_msg>Added empty class to autoselect option.<commit_after>var _autoselects = [];
function autoselectInit() {
  var els = document.getElementsByClassName("form-autoselect");
  for (var i=0; i<els.length; i++) {
    if (!els[i].className.match("autoselect-init")) {
      els[i].addClass("autoselect-init");
      _autoselects.push(new autoselect(els[i]));
    }
  }
  if (typeof(MutationObserver) == "function") {
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        autoselectObserve(mutation.target);
      });
    });
    var config = { childList: true, subtree: true };
    observer.observe(document.body, config);
  }
  else {
    setInterval(function() {
      autoselectObserve(document.body);
    }, 1000);
  }
}
function autoselectObserve(el) {
  var els = el.getElementsByClassName("form-autoselect");
  for (var i=0; i<els.length; i++) {
    if (!els[i].className.match("autoselect-init")) {
      els[i].addClass("autoselect-init");
      _autoselects.push(new autoselect(els[i]));
    }
  }
}

function autoselect(el) {

  this.tags = {
    input: el
  };

  this.init = function() {
    var self = this;
    this.optionActive = -1;
    this.tags.item = formGetItem(this.tags.input);
    this.tags.select = this.tags.item.getElementsByTagName("select")[0];
    this.tags.options = this.tags.item.getElementsByClassName("autoselect-options")[0];
    this.tags.input.addEventListener("blur", function(){ self.onBlur(); }, false);
    this.tags.input.addEventListener("focus", function(){ self.onFocus(); }, false);
    this.tags.input.addEventListener("keydown", function(e){ self.onKeyDown(e); }, false);
    this.tags.input.addEventListener("keyup", function(e){ self.onKeyUp(e); }, false);
    this.tags.input.addClass("autoselect-init");
    self.selectChange();
    if (typeof(MutationObserver) == "function") {
      var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
          self.selectChange(mutation.target);
        });
      });
      var config = { childList: true, subtree: true };
      observer.observe(this.tags.select, config);
    }
  }

  this.selectChange = function() {
    if (this.isDisabled()) {
      this.tags.input.setAttribute("disabled", true);
      this.tags.item.addClass("disabled");
    }
    else {
      this.tags.input.removeAttribute("disabled");
      this.tags.item.removeClass("disabled");
    }
    this.renderOptions();
  }

  this.renderOptions = function() {
    var value = this.tags.input.value.toLowerCase();
    this.tags.options.innerHTML = "";
    this.tags.option = [];
    this.optionActive = -1;
    for (var i=0; i<this.tags.select.options.length; i++) {
      var match = false;
      var lower = this.tags.select.options[i].text.toLowerCase();
      if (!value.length || lower.indexOf(value) != -1) {
        match = true;
      }
      else {
        var arr = lower.split(" ");
        for (var j=0; j<arr.length; j++) {
          if (arr[j].substr(0, value.length) == value) {
            match = true;
            break;
          }
        }
      }
      if (match) {
        this.tags.option[i] = document.createElement("div");
        this.tags.option[i].className = "autoselect-option";
        if (!this.tags.select.options[i].value.length)
          this.tags.option[i].className+= " empty";
        this.tags.option[i].innerHTML = this.tags.select.options[i].text;
        this.tags.options.appendChild(this.tags.option[i]);
        (function(self, n) {
          self.tags.option[n].addEventListener("click", function(){ self.optionClick(n); }, false);
        }(this, i));
      }
    }
  }

  this.onFocus = function() {
    this.renderOptions();
    this.tags.input.select();
    var self = this;
    setTimeout(function(){
      self.tags.input.select();
    }, 100);
  }

  this.onBlur = function() {
    if (!this.tags.input.value.length && this.tags.select.selectedIndex != 0) {
      this.tags.select.selectedIndex = 0;
      this.tags.select.trigger("change");
    }
  }

  this.isDisabled = function() {
    return this.tags.select.getAttribute("disabled") !== null;
  }

  /*
    e.keyCode
      37 = left
      38 = up
      39 = right
      40 = down
      27 = esc
      13 = enter
  */
  this.onKeyDown = function(e) {
    var code = e.keyCode;
    if (code == 13) {
      e.preventDefault();
      return false;
    }
    else if (code == 27) {
      this.tags.input.blur();
    }
  }
  this.onKeyUp = function(e) {
    var code = e.keyCode;
    if (code == 13) {
      e.preventDefault();
      this.optionEnter();
      return false;
    }
    else if (code == 40 || code == 38) {
      if (code == 40)
        this.optionDown();
      else
        this.optionUp();
    }
    else {
      this.renderOptions();
    }
  }

  this.optionUp = function() {
    for (var i=this.optionActive-1; i >= 0; i--) {
      if (this.tags.option[i]) {
        if (this.optionActive != -1)
          this.tags.option[this.optionActive].removeClass("active");
        this.tags.option[i].addClass("active");
        this.optionActive = i;
        break;
      }
    }
  }
  this.optionDown = function() {
    for (var i=this.optionActive+1; i < this.tags.select.options.length; i++) {
      if (this.tags.option[i]) {
        if (this.optionActive != -1)
          this.tags.option[this.optionActive].removeClass("active");
        this.tags.option[i].addClass("active");
        this.optionActive = i;
        break;
      }
    }
  }
  this.optionEnter = function() {
    if (this.optionActive != -1)
      this.optionClick(this.optionActive);
  }

  this.optionClick = function(n) {
    this.tags.input.value = (this.tags.select.value.length ? this.tags.select.options[n].text : "");
    this.tags.input.blur();
    this.tags.select.selectedIndex = n;
    this.tags.select.trigger("change");
  }

  this.init();

}

window.addEventListener("load", autoselectInit, false);<|endoftext|>


<commit_before>/* global sap, $ */

sap.ui.define([
    "com/sap/mentors/lemonaid/controller/BaseController",
    "com/sap/mentors/lemonaid/util/formatters",
    "sap/ui/model/Filter",
    "sap/ui/model/FilterOperator",
    "sap/ui/model/json/JSONModel"
], function(BaseController, formatters, Filter, FilterOperator, JSONModel) {
    "use strict";

    return BaseController.extend("com.sap.mentors.lemonaid.controller.MentorList", {

		formatters: formatters,

		/* =========================================================== */
		/* lifecycle methods                                           */
		/* =========================================================== */

		filters: {
				active: 	new sap.ui.model.Filter("MentorStatus/Id", "EQ", "active"),
				alumni: 	new sap.ui.model.Filter("MentorStatus/Id", "EQ", "alumni"),
				program: 	new sap.ui.model.Filter("MentorStatus/Id", "EQ", "program"),
				bandVegas:	new sap.ui.model.Filter("JambandLasVegas", "EQ", true),
				bandBcn:	new sap.ui.model.Filter("JambandBarcelona", "EQ", true),
				notpublic:	new sap.ui.model.Filter("PublicProfile", "EQ", false)
			},
		searchFilter: null, quickFilter: null,

		/**
		 * Called when the view controller is instantiated.
		 * @public
		 */
        onInit: function() {
        	this.table = this.byId("mentorsTable");
        	this.map = this.byId("map");
            this.ui = new JSONModel({ tableBusyDelay: 0, count: 0 });
            this.model = this.getComponent().getModel();
            this.view = this.getView();
            this.router = this.getRouter();
            this.view.setModel(this.ui, "ui");
            this.router.getRoute("Mentors").attachMatched(this.onRouteMatched, this);

			// Make sure, busy indication is showing immediately so there is no
			// break after the busy indication for loading the view's meta data is
			// ended (see promise 'oWhenMetadataIsLoaded' in AppController)
			if (this.table) {
				var that = this,
					originalBusyDelay = this.table.getBusyIndicatorDelay();
				this.table.attachEventOnce("updateFinished", function(){
					// Restore original busy indicator delay for worklist's table
					that.ui.setProperty("/tableBusyDelay", originalBusyDelay);
				});
			}
        },

        onSearchPressed: function(event) {
            var search = event.getParameters().query;

				var afilters = [];
				var outerFilters = [];
				var searchTerms = search.split(","); //words separated by ',' are considered as separate search terms.
                var umlaute = ["oe","ae","ue"]
                for (var k = 0; k < searchTerms.length; k++) {
                    for(var i = 0; i<umlaute.length; i++){
                        if(searchTerms[k].includes(umlaute[i])){
                            var searchTermHelper = searchTerms[k].split(umlaute[i]);
                            var arrayLength = searchTerms.length;
                            searchTerms[arrayLength] = "";
                            for(var j =0; j<searchTermHelper.length; j++){
                                if(j>0){
                                    switch (umlaute[i]){
                                        case "oe":
                                            searchTerms[arrayLength] = searchTerms[arrayLength]+"ö";
                                            break;
                                        case "ae":
                                            searchTerms[arrayLength] = searchTerms[arrayLength]+"ä";
                                            break;
                                        case "ue":
                                            searchTerms[arrayLength] = searchTerms[arrayLength]+"ü";
                                            break;
                                    }
                                }
                                searchTerms[arrayLength] =  searchTerms[arrayLength]+searchTermHelper[j];
                            }
                        }
                    }
					afilters.push(new Filter("FullName", FilterOperator.Contains, searchTerms[k]));
					afilters.push(new Filter("ShirtNumber", FilterOperator.Contains, searchTerms[k]));
					afilters.push(new Filter("RelationshipToSap/Name", FilterOperator.Contains, searchTerms[k]));
					afilters.push(new Filter("MentorStatus/Name", FilterOperator.Contains, searchTerms[k]));
                    afilters.push(new Filter("SapExpertise1/Name", FilterOperator.Contains, searchTerms[k]));
                    afilters.push(new Filter("SapExpertise2/Name", FilterOperator.Contains, searchTerms[k]));
                    afilters.push(new Filter("SapExpertise3/Name", FilterOperator.Contains, searchTerms[k]));
                    outerFilters.push(new Filter(afilters));
					afilters = [];
				}

            this.searchFilter = search ? new Filter(outerFilters) : null;
            this._applyFilters();
        },

		/* =========================================================== */
		/* event handlers                                              */
		/* =========================================================== */

		/**
		 * Triggered by the table's 'updateFinished' event: after new table
		 * data is available, this handler method updates the table counter.
		 * This should only happen if the update was successful, which is
		 * why this handler is attached to 'updateFinished' and not to the
		 * table's list binding's 'dataReceived' method.
		 * @param {sap.ui.base.Event} oEvent the update finished event
		 * @public
		 */
		onUpdateFinished : function(event) {
			var that = this;
			var count = event.getParameter("total");
			this.ui.setProperty("/count", count);
			if (count && event.getSource().getBinding("items").isLengthFinal()) {
				$.each(this.filters, function (name, filters) {
					that.model.read("/Mentors/$count", {
						filters: [ filters ],
						success: function (oData) {
							that.ui.setProperty("/" + name, oData);
						}
					});
				});
			}
		},

        onMentorDetailPress: function(event) {
            this.getRouter().navTo("Mentor", {
                Id: event.getSource().getBindingContext().getProperty("Id")
            });
        },

        onAddNewMentor: function () {
            this.getRouter().navTo("MentorAddition");
        },

		/**
		 * Event handler when a filter tab gets pressed
		 * @param {sap.ui.base.Event} oEvent the filter tab event
		 * @public
		 */
		onQuickFilter: function(oEvent) {
			var key = oEvent.getParameter("key");
			this.quickFilter = key === "all" ? null : this.filters[key];
			this._applyFilters();
		},

		onRouteMatched: function() {
		},

		/**
         * Event handler for Map Marker click
         * @param  {sap.ui.base.Event} oEvent for click event
         * @public
         */
        onMarkerClick: function(oEvent) {
            if (this.activeMarker) {
                if (this.activeMarker.isOpen) {
                    this.activeMarker.infoWindowClose();
                    this.activeMarker.isOpen = false;
                } else {
                    this.activeMarker.isOpen = true; //same marker reopen
                }
            }

            if (this.activeMarker !== oEvent.getSource()) {
                this.activeMarker = oEvent.getSource();
                this.activeMarker.isOpen = true;
            }
        },

		/* =========================================================== */
		/* internal methods                                            */
		/* =========================================================== */

		_applyFilters: function() {
			var aFilter = [];
			if (this.searchFilter)	{ aFilter.push(this.searchFilter); }
			if (this.quickFilter)	{ aFilter.push(this.quickFilter); }
			var filter = aFilter.length === 0 ? null : new Filter(aFilter, true);
            this.table.getBinding("items").filter(filter);
            this.map.getBinding("markers").filter(filter);
		}

    });

});
<commit_msg>Simplified Umlaut replacement<commit_after>/* global sap, $ */

sap.ui.define([
    "com/sap/mentors/lemonaid/controller/BaseController",
    "com/sap/mentors/lemonaid/util/formatters",
    "sap/ui/model/Filter",
    "sap/ui/model/FilterOperator",
    "sap/ui/model/json/JSONModel"
], function(BaseController, formatters, Filter, FilterOperator, JSONModel) {
    "use strict";

    return BaseController.extend("com.sap.mentors.lemonaid.controller.MentorList", {

		formatters: formatters,

		/* =========================================================== */
		/* lifecycle methods                                           */
		/* =========================================================== */

		filters: {
				active: 	new sap.ui.model.Filter("MentorStatus/Id", "EQ", "active"),
				alumni: 	new sap.ui.model.Filter("MentorStatus/Id", "EQ", "alumni"),
				program: 	new sap.ui.model.Filter("MentorStatus/Id", "EQ", "program"),
				bandVegas:	new sap.ui.model.Filter("JambandLasVegas", "EQ", true),
				bandBcn:	new sap.ui.model.Filter("JambandBarcelona", "EQ", true),
				notpublic:	new sap.ui.model.Filter("PublicProfile", "EQ", false)
			},
		searchFilter: null, quickFilter: null,

		/**
		 * Called when the view controller is instantiated.
		 * @public
		 */
        onInit: function() {
        	this.table = this.byId("mentorsTable");
        	this.map = this.byId("map");
            this.ui = new JSONModel({ tableBusyDelay: 0, count: 0 });
            this.model = this.getComponent().getModel();
            this.view = this.getView();
            this.router = this.getRouter();
            this.view.setModel(this.ui, "ui");
            this.router.getRoute("Mentors").attachMatched(this.onRouteMatched, this);

			// Make sure, busy indication is showing immediately so there is no
			// break after the busy indication for loading the view's meta data is
			// ended (see promise 'oWhenMetadataIsLoaded' in AppController)
			if (this.table) {
				var that = this,
					originalBusyDelay = this.table.getBusyIndicatorDelay();
				this.table.attachEventOnce("updateFinished", function(){
					// Restore original busy indicator delay for worklist's table
					that.ui.setProperty("/tableBusyDelay", originalBusyDelay);
				});
			}
        },

        onSearchPressed: function(event) {
            var search = event.getParameters().query;

				var afilters = [];
				var outerFilters = [];
				var searchTerms = search.split(","); //words separated by ',' are considered as separate search terms.
                var umlaute = [["oe","ö"],["ae","ä"],["ue","ü"],["OE","Ö"],["AE","Ä"],["UE","Ü"],["Oe","Ö"],["Ae","Ä"],["Ue","Ü"],["ss","ß"]] //Feel free to add more Umlauts and their replacements
                for (var k = 0; k < searchTerms.length; k++) {
                    for(var i = 0; i<umlaute.length; i++){
                        if(searchTerms[k].includes(umlaute[i][0])){
							searchTerms[searchTerms.length] = searchTerms[k].replace(umlaute[i][0],umlaute[i][1])
                        }
                    }
					afilters.push(new Filter("FullName", FilterOperator.Contains, searchTerms[k]));
					afilters.push(new Filter("ShirtNumber", FilterOperator.Contains, searchTerms[k]));
					afilters.push(new Filter("RelationshipToSap/Name", FilterOperator.Contains, searchTerms[k]));
					afilters.push(new Filter("MentorStatus/Name", FilterOperator.Contains, searchTerms[k]));
                    afilters.push(new Filter("SapExpertise1/Name", FilterOperator.Contains, searchTerms[k]));
                    afilters.push(new Filter("SapExpertise2/Name", FilterOperator.Contains, searchTerms[k]));
                    afilters.push(new Filter("SapExpertise3/Name", FilterOperator.Contains, searchTerms[k]));
                    outerFilters.push(new Filter(afilters));
					afilters = [];
				}

            this.searchFilter = search ? new Filter(outerFilters) : null;
            this._applyFilters();
        },

		/* =========================================================== */
		/* event handlers                                              */
		/* =========================================================== */

		/**
		 * Triggered by the table's 'updateFinished' event: after new table
		 * data is available, this handler method updates the table counter.
		 * This should only happen if the update was successful, which is
		 * why this handler is attached to 'updateFinished' and not to the
		 * table's list binding's 'dataReceived' method.
		 * @param {sap.ui.base.Event} oEvent the update finished event
		 * @public
		 */
		onUpdateFinished : function(event) {
			var that = this;
			var count = event.getParameter("total");
			this.ui.setProperty("/count", count);
			if (count && event.getSource().getBinding("items").isLengthFinal()) {
				$.each(this.filters, function (name, filters) {
					that.model.read("/Mentors/$count", {
						filters: [ filters ],
						success: function (oData) {
							that.ui.setProperty("/" + name, oData);
						}
					});
				});
			}
		},

        onMentorDetailPress: function(event) {
            this.getRouter().navTo("Mentor", {
                Id: event.getSource().getBindingContext().getProperty("Id")
            });
        },

        onAddNewMentor: function () {
            this.getRouter().navTo("MentorAddition");
        },

		/**
		 * Event handler when a filter tab gets pressed
		 * @param {sap.ui.base.Event} oEvent the filter tab event
		 * @public
		 */
		onQuickFilter: function(oEvent) {
			var key = oEvent.getParameter("key");
			this.quickFilter = key === "all" ? null : this.filters[key];
			this._applyFilters();
		},

		onRouteMatched: function() {
		},

		/**
         * Event handler for Map Marker click
         * @param  {sap.ui.base.Event} oEvent for click event
         * @public
         */
        onMarkerClick: function(oEvent) {
            if (this.activeMarker) {
                if (this.activeMarker.isOpen) {
                    this.activeMarker.infoWindowClose();
                    this.activeMarker.isOpen = false;
                } else {
                    this.activeMarker.isOpen = true; //same marker reopen
                }
            }

            if (this.activeMarker !== oEvent.getSource()) {
                this.activeMarker = oEvent.getSource();
                this.activeMarker.isOpen = true;
            }
        },

		/* =========================================================== */
		/* internal methods                                            */
		/* =========================================================== */

		_applyFilters: function() {
			var aFilter = [];
			if (this.searchFilter)	{ aFilter.push(this.searchFilter); }
			if (this.quickFilter)	{ aFilter.push(this.quickFilter); }
			var filter = aFilter.length === 0 ? null : new Filter(aFilter, true);
            this.table.getBinding("items").filter(filter);
            this.map.getBinding("markers").filter(filter);
		}

    });

});
<|endoftext|>


<commit_before>'use strict';

// Required options for creating board in jade
var jade = {
    background: '',
    tickets: [],
    pretty: true
};

// Required options for webshot
var webshot = {
    siteType:   'html',
    shotSize: {
        width:  1920,
        height: 1080
    },
    shotOffset: {
    	left: 	0,
		right: 	0,
		top: 	0,
		bottom: 0
	},
    renderDelay: 10
};

// Path where jade file can be found on static folder
var pathBg = __dirname + '/bg/';
var pathJade = __dirname + '/site.jade';

module.exports = {
    jade: jade,
    zoomFactor: 1,
    webshot: webshot,
    pathBg: pathBg,
    pathJade: pathJade
}<commit_msg>Fixed custom background<commit_after>'use strict';

// Required options for creating board in jade
var jade = {
    background: '',
    tickets: [],
    pretty: true
};

// Required options for webshot
var webshot = {
    siteType:   'html',
    shotSize: {
        width:  1920,
        height: 1080
    },
    shotOffset: {
    	left: 	0,
		right: 	0,
		top: 	0,
		bottom: 0
	},
    renderDelay: 10
};

// Path where jade file can be found on static folder
var pathBg = 'http://localhost:9003/bg/';
var pathJade = __dirname + '/site.jade';

module.exports = {
    jade: jade,
    zoomFactor: 1,
    webshot: webshot,
    pathBg: pathBg,
    pathJade: pathJade
}<|endoftext|>


<commit_before>"use strict";

var ObjectId = require("mongodb").ObjectId;
require("mongodb-toolkit");
var DLModels = require("dl-models");
var map = DLModels.map;
var PurchaseRequest = DLModels.purchasing.PurchaseRequest;
var generateCode = require("../../utils/code-generator");
var BaseManager = require("module-toolkit").BaseManager;
var i18n = require("dl-i18n");
var UnitManager = require("../master/unit-manager");
var BudgetManager = require("../master/budget-manager");
var CategoryManager = require("../master/category-manager");
var ProductManager = require("../master/product-manager");

module.exports = class PurchaseRequestManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.moduleId = "PR";
        this.year = (new Date()).getFullYear().toString().substring(2, 4);
        this.collection = this.db.use(map.purchasing.collection.PurchaseRequest);

        this.unitManager = new UnitManager(db, user);
        this.budgetManager = new BudgetManager(db, user);
        this.categoryManager = new CategoryManager(db, user);
        this.productManager = new ProductManager(db, user);
    }

    _getQuery(paging) {
        var deletedFilter = {
            _deleted: false
        },
            keywordFilter = {};

        var query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");

            var filterNo = {
                "no": {
                    "$regex": regex
                }
            };

            var filterUnitDivisionName = {
                "unit.division.name": {
                    "$regex": regex
                }
            };
            var filterUnitName = {
                "unit.name": {
                    "$regex": regex
                }
            };

            var filterCategory = {
                "category.name": {
                    "$regex": regex
                }
            };

            keywordFilter = {
                "$or": [filterNo, filterUnitDivisionName, filterUnitName, filterCategory]
            };
        }
        query = {
            "$and": [deletedFilter, paging.filter, keywordFilter]
        };
        return query;
    }

    _validate(purchaseRequest) {
        var errors = {};
        var valid = purchaseRequest;

        var getPurchaseRequestPromise = this.collection.singleOrDefault({
            _id: {
                '$ne': new ObjectId(valid._id)
            },
            no: valid.no
        });

        var getUnit = valid.unitId && valid.unitId.toString().trim() !== "" ? this.unitManager.getSingleByIdOrDefault(valid.unitId) : Promise.resolve(null);
        var getCategory = valid.categoryId && valid.categoryId.toString().trim() !== "" ? this.categoryManager.getSingleByIdOrDefault(valid.categoryId) : Promise.resolve(null);
        var getBudget = valid.budgetId && valid.budgetId.toString().trim() !== "" ? this.budgetManager.getSingleByIdOrDefault(valid.budgetId) : Promise.resolve(null);
        var getProduct = [];

        valid.items = valid.items instanceof Array ? valid.items : [];
        for (var _item of valid.items)
            getProduct.push(_item.productId && _item.productId.toString().trim() !== "" ? this.productManager.getSingleByIdOrDefault(_item.productId) : Promise.resolve(null));

        return Promise.all([getPurchaseRequestPromise, getUnit, getCategory, getBudget].concat(getProduct))
            .then(results => {
                var _purchaseRequest = results[0];
                var _unit = results[1];
                var _category = results[2];
                var _budget = results[3];
                var _products = results.slice(4, results.length);

                if (_purchaseRequest)
                    errors["no"] = i18n.__("PurchaseRequest.no.isExists:%s is exists", i18n.__("PurchaseRequest.product._:No"));

                if (!valid.date || valid.date == "" || valid.date == "undefined")
                    errors["date"] = i18n.__("PurchaseRequest.date.isRequired:%s is required", i18n.__("PurchaseRequest.date._:Date")); //"Tanggal PR tidak boleh kosong";

                if (!_unit)
                    errors["unit"] = i18n.__("PurchaseRequest.unit.isRequired:%s is not exists", i18n.__("PurchaseRequest.unit._:Unit")); //"Unit tidak boleh kosong";
                else if (!valid.unitId)
                    errors["unit"] = i18n.__("PurchaseRequest.unit.isRequired:%s is required", i18n.__("PurchaseRequest.unit._:Unit")); //"Unit tidak boleh kosong";

                if (!_category)
                    errors["category"] = i18n.__("PurchaseRequest.category.isRequired:%s is not exists", i18n.__("PurchaseRequest.category._:Category")); //"Category tidak boleh kosong";
                else if (!valid.categoryId)
                    errors["category"] = i18n.__("PurchaseRequest.category.isRequired:%s is required", i18n.__("PurchaseRequest.category._:Category")); //"Category tidak boleh kosong";

                if (!_budget)
                    errors["budget"] = i18n.__("PurchaseRequest.budget.name.isRequired:%s is not exists", i18n.__("PurchaseRequest.budget.name._:Budget")); //"Budget tidak boleh kosong";
                else if (!valid.budget._id)
                    errors["budget"] = i18n.__("PurchaseRequest.budget.name.isRequired:%s is required", i18n.__("PurchaseRequest.budget.name._:Budget")); //"Budget tidak boleh kosong";

                if (!valid.expectedDeliveryDate || valid.expectedDeliveryDate === "" || valid.expectedDeliveryDate === "undefined")
                    valid.expectedDeliveryDate = "";

                if (valid.items && valid.items.length <= 0) {
                    errors["items"] = i18n.__("PurchaseRequest.items.isRequired:%s is required", i18n.__("PurchaseRequest.items._:Item")); //"Harus ada minimal 1 barang";
                }
                else {
                    var itemErrors = [];
                    for (var item of valid.items) {
                        var itemError = {};
                        if (!item.product || !item.product._id)
                            itemError["product"] = i18n.__("PurchaseRequest.items.product.name.isRequired:%s is required", i18n.__("PurchaseRequest.items.product.name._:Name")); //"Nama barang tidak boleh kosong";
                        if (item.quantity <= 0)
                            itemError["quantity"] = i18n.__("PurchaseRequest.items.quantity.isRequired:%s is required", i18n.__("PurchaseRequest.items.quantity._:Quantity")); //Jumlah barang tidak boleh kosong";

                        if (Object.getOwnPropertyNames(itemError).length > 0)
                            itemErrors.push(itemError);
                    }
                    if (itemErrors.length > 0)
                        errors.items = itemErrors;
                }

                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require("module-toolkit").ValidationError;
                    return Promise.reject(new ValidationError("data does not pass validation", errors));
                }

                valid.unitId = _unit._id;
                valid.unit = _unit;

                valid.categoryId = _category._id;
                valid.category = _category;

                valid.budgetId = _budget._id;
                valid.budget = _budget;

                for (var prItem of valid.items) {
                    for (var _product of _products) {
                        if (prItem.product._id.toString() === _product._id.toString()) {
                            prItem.product = _product;
                            prItem.uom = _product.uom;
                            break;
                        }
                    }
                }

                if (!valid.stamp)
                    valid = new PurchaseRequest(valid);

                valid.stamp(this.user.username, "manager");
                return Promise.resolve(valid);
            });
    }

    create(purchaseRequest) {
        return new Promise((resolve, reject) => {
            var dateFormat = "MMYY";
            var locale = "id-ID";
            var moment = require("moment");
            moment.locale(locale);
            this._validate(purchaseRequest)
                .then(validPurchaseRequest => {
                    validPurchaseRequest.no = generateCode();
                    if (validPurchaseRequest.expectedDeliveryDate === "undefined") {
                        validPurchaseRequest.expectedDeliveryDate = "";
                    }
                    this.collection.insert(validPurchaseRequest)
                        .then(id => {
                            resolve(id);
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });

        });
    }

    post(listPurchaseRequest) {
        var purchaseRequests = [];
        var tasks = [];
        return new Promise((resolve, reject) => {
            for (var purchaseRequest of listPurchaseRequest) {
                purchaseRequests.push(this.getSingleByIdOrDefault(purchaseRequest._id));
            }
            Promise.all(purchaseRequests)
                .then(validPurchaseRequest => {
                    for (var pr of listPurchaseRequest) {
                        for (var _pr of validPurchaseRequest) {
                            if (_pr._id.equals(pr._id)) {
                                _pr.isPosted = true;
                                tasks.push(this.update(_pr));
                                break;
                            }
                        }

                    }
                    Promise.all(tasks)
                        .then(result => {
                            resolve(result);
                        })
                        .catch(e => {
                            reject(e);
                        });

                })
                .catch(e => {
                    reject(e);
                });
        });

    }

    pdf(id) {
        return new Promise((resolve, reject) => {

            this.getSingleById(id)
                .then(purchaseRequest => {
                    var getDefinition = require("../../pdf/definitions/purchase-request");
                    var definition = getDefinition(purchaseRequest);

                    var generatePdf = require("../../pdf/pdf-generator");
                    generatePdf(definition)
                        .then(binary => {
                            resolve(binary);
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });

        });
    }

    getDataPRMonitoring(unitId, categoryId, budgetId, PRNo, dateFrom, dateTo) {
        return new Promise((resolve, reject) => {
            var sorting = {
                "date": -1,
                "no": 1
            };
            var query = Object.assign({});

            if (unitId !== "undefined" && unitId !== "") {
                Object.assign(query, { unitId: new ObjectId(unitId) });
            }
            if (categoryId !== "undefined" && categoryId !== "") {
                Object.assign(query, { categoryId: new ObjectId(categoryId) });
            }
            if (budgetId !== "undefined" && budgetId !== "") {
                Object.assign(query, { budgetId: new ObjectId(budgetId) });
            }
            if (PRNo !== "undefined" && PRNo !== "") {
                Object.assign(query, { "no": PRNo });
            }
            if (dateFrom !== "undefined" && dateFrom !== "" && dateFrom !== "null" && dateTo !== "undefined" && dateTo !== "" && dateTo !== "null") {
                Object.assign(query, {
                    date: {
                        $gte: dateFrom,
                        $lte: dateTo
                    }
                });
            }
            query = Object.assign(query, {
                _createdBy: this.user.username,
                _deleted: false,
                isPosted: true
            });

            this.collection.find(query).sort(sorting).toArray()
                .then((purchaseRequests) => {
                    resolve(purchaseRequests);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.purchasing.collection.PurchaseRequest}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var noIndex = {
            name: `ix_${map.purchasing.collection.PurchaseRequest}_no`,
            key: {
                no: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, noIndex]);
    }
};<commit_msg>add _beforeInsert<commit_after>"use strict";

var ObjectId = require("mongodb").ObjectId;
require("mongodb-toolkit");
var DLModels = require("dl-models");
var map = DLModels.map;
var PurchaseRequest = DLModels.purchasing.PurchaseRequest;
var CodeGenerator = require("../../utils/code-generator");
var BaseManager = require("module-toolkit").BaseManager;
var i18n = require("dl-i18n");
var UnitManager = require("../master/unit-manager");
var BudgetManager = require("../master/budget-manager");
var CategoryManager = require("../master/category-manager");
var ProductManager = require("../master/product-manager");

module.exports = class PurchaseRequestManager extends BaseManager {
    constructor(db, user) {
        super(db, user);
        this.moduleId = "PR";
        this.year = (new Date()).getFullYear().toString().substring(2, 4);
        this.collection = this.db.use(map.purchasing.collection.PurchaseRequest);

        this.unitManager = new UnitManager(db, user);
        this.budgetManager = new BudgetManager(db, user);
        this.categoryManager = new CategoryManager(db, user);
        this.productManager = new ProductManager(db, user);
    }

    _getQuery(paging) {
        var deletedFilter = {
            _deleted: false
        },
            keywordFilter = {};

        var query = {};

        if (paging.keyword) {
            var regex = new RegExp(paging.keyword, "i");

            var filterNo = {
                "no": {
                    "$regex": regex
                }
            };

            var filterUnitDivisionName = {
                "unit.division.name": {
                    "$regex": regex
                }
            };
            var filterUnitName = {
                "unit.name": {
                    "$regex": regex
                }
            };

            var filterCategory = {
                "category.name": {
                    "$regex": regex
                }
            };

            keywordFilter = {
                "$or": [filterNo, filterUnitDivisionName, filterUnitName, filterCategory]
            };
        }
        query = {
            "$and": [deletedFilter, paging.filter, keywordFilter]
        };
        return query;
    }

    _validate(purchaseRequest) {
        var errors = {};
        var valid = purchaseRequest;

        var getPurchaseRequestPromise = this.collection.singleOrDefault({
            _id: {
                '$ne': new ObjectId(valid._id)
            },
            no: valid.no
        });

        var getUnit = valid.unitId && valid.unitId.toString().trim() !== "" ? this.unitManager.getSingleByIdOrDefault(valid.unitId) : Promise.resolve(null);
        var getCategory = valid.categoryId && valid.categoryId.toString().trim() !== "" ? this.categoryManager.getSingleByIdOrDefault(valid.categoryId) : Promise.resolve(null);
        var getBudget = valid.budgetId && valid.budgetId.toString().trim() !== "" ? this.budgetManager.getSingleByIdOrDefault(valid.budgetId) : Promise.resolve(null);
        var getProduct = [];

        valid.items = valid.items instanceof Array ? valid.items : [];
        for (var _item of valid.items)
            getProduct.push(_item.productId && _item.productId.toString().trim() !== "" ? this.productManager.getSingleByIdOrDefault(_item.productId) : Promise.resolve(null));

        return Promise.all([getPurchaseRequestPromise, getUnit, getCategory, getBudget].concat(getProduct))
            .then(results => {
                var _purchaseRequest = results[0];
                var _unit = results[1];
                var _category = results[2];
                var _budget = results[3];
                var _products = results.slice(4, results.length);

                if (_purchaseRequest)
                    errors["no"] = i18n.__("PurchaseRequest.no.isExists:%s is exists", i18n.__("PurchaseRequest.product._:No"));

                if (!valid.date || valid.date == "" || valid.date == "undefined")
                    errors["date"] = i18n.__("PurchaseRequest.date.isRequired:%s is required", i18n.__("PurchaseRequest.date._:Date")); //"Tanggal PR tidak boleh kosong";

                if (!_unit)
                    errors["unit"] = i18n.__("PurchaseRequest.unit.isRequired:%s is not exists", i18n.__("PurchaseRequest.unit._:Unit")); //"Unit tidak boleh kosong";
                else if (!valid.unitId)
                    errors["unit"] = i18n.__("PurchaseRequest.unit.isRequired:%s is required", i18n.__("PurchaseRequest.unit._:Unit")); //"Unit tidak boleh kosong";

                if (!_category)
                    errors["category"] = i18n.__("PurchaseRequest.category.isRequired:%s is not exists", i18n.__("PurchaseRequest.category._:Category")); //"Category tidak boleh kosong";
                else if (!valid.categoryId)
                    errors["category"] = i18n.__("PurchaseRequest.category.isRequired:%s is required", i18n.__("PurchaseRequest.category._:Category")); //"Category tidak boleh kosong";

                if (!_budget)
                    errors["budget"] = i18n.__("PurchaseRequest.budget.name.isRequired:%s is not exists", i18n.__("PurchaseRequest.budget.name._:Budget")); //"Budget tidak boleh kosong";
                else if (!valid.budget._id)
                    errors["budget"] = i18n.__("PurchaseRequest.budget.name.isRequired:%s is required", i18n.__("PurchaseRequest.budget.name._:Budget")); //"Budget tidak boleh kosong";

                if (!valid.expectedDeliveryDate || valid.expectedDeliveryDate === "" || valid.expectedDeliveryDate === "undefined")
                    valid.expectedDeliveryDate = "";

                if (valid.items && valid.items.length <= 0) {
                    errors["items"] = i18n.__("PurchaseRequest.items.isRequired:%s is required", i18n.__("PurchaseRequest.items._:Item")); //"Harus ada minimal 1 barang";
                }
                else {
                    var itemErrors = [];
                    for (var item of valid.items) {
                        var itemError = {};
                        if (!item.product || !item.product._id)
                            itemError["product"] = i18n.__("PurchaseRequest.items.product.name.isRequired:%s is required", i18n.__("PurchaseRequest.items.product.name._:Name")); //"Nama barang tidak boleh kosong";
                        if (item.quantity <= 0)
                            itemError["quantity"] = i18n.__("PurchaseRequest.items.quantity.isRequired:%s is required", i18n.__("PurchaseRequest.items.quantity._:Quantity")); //Jumlah barang tidak boleh kosong";

                        if (Object.getOwnPropertyNames(itemError).length > 0)
                            itemErrors.push(itemError);
                    }
                    if (itemErrors.length > 0)
                        errors.items = itemErrors;
                }

                if (Object.getOwnPropertyNames(errors).length > 0) {
                    var ValidationError = require("module-toolkit").ValidationError;
                    return Promise.reject(new ValidationError("data does not pass validation", errors));
                }

                valid.unitId = _unit._id;
                valid.unit = _unit;

                valid.categoryId = _category._id;
                valid.category = _category;

                valid.budgetId = _budget._id;
                valid.budget = _budget;

                for (var prItem of valid.items) {
                    for (var _product of _products) {
                        if (prItem.product._id.toString() === _product._id.toString()) {
                            prItem.product = _product;
                            prItem.uom = _product.uom;
                            break;
                        }
                    }
                }

                if (!valid.stamp)
                    valid = new PurchaseRequest(valid);

                valid.stamp(this.user.username, "manager");
                return Promise.resolve(valid);
            });
    }

    _beforeInsert(purchaseRequest) {
        purchaseRequest.no = CodeGenerator();
        return Promise.resolve(purchaseRequest);
    }

    post(listPurchaseRequest) {
        var purchaseRequests = [];
        var tasks = [];
        return new Promise((resolve, reject) => {
            for (var purchaseRequest of listPurchaseRequest) {
                purchaseRequests.push(this.getSingleByIdOrDefault(purchaseRequest._id));
            }
            Promise.all(purchaseRequests)
                .then(validPurchaseRequest => {
                    for (var pr of listPurchaseRequest) {
                        for (var _pr of validPurchaseRequest) {
                            if (_pr._id.equals(pr._id)) {
                                _pr.isPosted = true;
                                tasks.push(this.update(_pr));
                                break;
                            }
                        }

                    }
                    Promise.all(tasks)
                        .then(result => {
                            resolve(result);
                        })
                        .catch(e => {
                            reject(e);
                        });

                })
                .catch(e => {
                    reject(e);
                });
        });

    }

    pdf(id) {
        return new Promise((resolve, reject) => {

            this.getSingleById(id)
                .then(purchaseRequest => {
                    var getDefinition = require("../../pdf/definitions/purchase-request");
                    var definition = getDefinition(purchaseRequest);

                    var generatePdf = require("../../pdf/pdf-generator");
                    generatePdf(definition)
                        .then(binary => {
                            resolve(binary);
                        })
                        .catch(e => {
                            reject(e);
                        });
                })
                .catch(e => {
                    reject(e);
                });

        });
    }

    getDataPRMonitoring(unitId, categoryId, budgetId, PRNo, dateFrom, dateTo) {
        return new Promise((resolve, reject) => {
            var sorting = {
                "date": -1,
                "no": 1
            };
            var query = Object.assign({});

            if (unitId !== "undefined" && unitId !== "") {
                Object.assign(query, { unitId: new ObjectId(unitId) });
            }
            if (categoryId !== "undefined" && categoryId !== "") {
                Object.assign(query, { categoryId: new ObjectId(categoryId) });
            }
            if (budgetId !== "undefined" && budgetId !== "") {
                Object.assign(query, { budgetId: new ObjectId(budgetId) });
            }
            if (PRNo !== "undefined" && PRNo !== "") {
                Object.assign(query, { "no": PRNo });
            }
            if (dateFrom !== "undefined" && dateFrom !== "" && dateFrom !== "null" && dateTo !== "undefined" && dateTo !== "" && dateTo !== "null") {
                Object.assign(query, {
                    date: {
                        $gte: dateFrom,
                        $lte: dateTo
                    }
                });
            }
            query = Object.assign(query, {
                _createdBy: this.user.username,
                _deleted: false,
                isPosted: true
            });

            this.collection.find(query).sort(sorting).toArray()
                .then((purchaseRequests) => {
                    resolve(purchaseRequests);
                })
                .catch(e => {
                    reject(e);
                });
        });
    }

    _createIndexes() {
        var dateIndex = {
            name: `ix_${map.purchasing.collection.PurchaseRequest}__updatedDate`,
            key: {
                _updatedDate: -1
            }
        };

        var noIndex = {
            name: `ix_${map.purchasing.collection.PurchaseRequest}_no`,
            key: {
                no: 1
            },
            unique: true
        };

        return this.collection.createIndexes([dateIndex, noIndex]);
    }
};<|endoftext|>


<commit_before>var fs = require('fs');

function sortObject(obj)
{
  if(typeof obj !== 'object')
    return obj;
  var tObj = {};
  Object.keys(obj).sort().forEach( function(key) {
    tObj[key] = sortObject(obj[key])
  } )
  return tObj;
}

function process(path){
  fs.readdir('../'+path, function(err, files){
    if(err){
      console.log("Directory ../"+path+" caused an Error", err);
      return
    }
    for(var i=0; i<files.length; i++) {
      if( files[i].match(/\.json$/) ) {
        try {
          console.log('starting '+path+'/'+files[i]);
          var item = JSON.parse(fs.readFileSync('../'+path+'/'+files[i]));
          fs.writeFileSync(path+'/'+files[i], JSON.stringify(sortObject(item),undefined, 2));
        } catch(e) {
          console.error("SOMETHING IS WRONG with ",path+files[i],e)
        }
      }
    }
  })
}

['points', 'topics', 'services', 'index'].forEach(process);
<commit_msg>repairing preifier.js<commit_after>var fs = require('fs');

function sortObject(obj, strict)
{
  if(obj instanceof Array) {
    var ary;
    if(strict) ary =  obj.sort();
    else ary = obj
    return ary
  }
  if(typeof obj === 'object') {
    var tObj = {};
    Object.keys(obj).sort().forEach( function(key) {
      tObj[key] = sortObject(obj[key])
    } )
    return tObj;
  }
  return obj;
}

function process(path){
  fs.readdir('../'+path, function(err, files){
    if(err){
      console.log("Directory ../"+path+" caused an Error", err);
      return
    }
    for(var i=0; i<files.length; i++) {
      if( files[i].match(/\.json$/) ) {
        try {
          console.log('starting '+path+'/'+files[i]);
          var item = JSON.parse(fs.readFileSync('../'+path+'/'+files[i]));
          fs.writeFileSync(path+'/'+files[i], JSON.stringify(sortObject(item, true),undefined, 2));
        } catch(e) {
          console.error("SOMETHING IS WRONG with ",path+files[i],e)
        }
      }
    }
  })
}

['points', 'topics', 'services', 'index'].forEach(process);
<|endoftext|>


<commit_before>var debug = require('debug')('SebastiaanLuca:Controls:Controls');

var util = require('util');
var EventEmitter = require('events').EventEmitter;

var Gpio = require('onoff').Gpio;
var Button = require('modules/SebastiaanLuca/Controls/src/Peripherals/Button.js');

//

var Controls = function Controls() {

    var self = this;

    // Input
    var btnPlayPause = new Button(17);
    var btnPlayPreviousTrack = new Button(27);
    var btnPlayNextTrack = new Button(22);

    // Output
    var appRunningIndicatorLed = new Gpio(25, 'out');

    var init = function () {
        // Turn on LED indicating application is running
        appRunningIndicatorLed.writeSync(1);
    };

    var quitHandler = function () {
        debug('Cleaning up our mess.');

        // Clear perhipherals
        appRunningIndicatorLed.unexport();
    };

    btnPlayPause.on('pressed', function () {
        self.emit('playPauseButtonPressed');
    });

    btnPlayPreviousTrack.on('pressed', function () {
        self.emit('playPreviousTrackButtonPressed');
    });

    btnPlayNextTrack.on('pressed', function () {
        self.emit('playNextTrackButtonPressed');
    });

    // Gracefully exit on CTRL+C and errors
    process.on('forceQuitApplication', quitHandler);

    init();

};

//

// Class inherits EventEmitter so we can dispatch and listen to events on the object itself
util.inherits(Controls, EventEmitter);

module.exports = new Controls();<commit_msg>Add volume control (in progress)<commit_after>var debug = require('debug')('SebastiaanLuca:Controls:Controls');

var util = require('util');
var EventEmitter = require('events').EventEmitter;

var Gpio = require('onoff').Gpio;
var PwmGpio = require('pigpio').Gpio;

var Button = require('modules/SebastiaanLuca/Controls/src/Peripherals/Button.js');

//

var Controls = function Controls() {

    var self = this;

    // Input
    var btnPlayPause = new Button(17);
    var btnPlayPreviousTrack = new Button(27);
    var btnPlayNextTrack = new Button(22);

    // Output
    var appRunningIndicatorLed = new Gpio(25, 'out');

    var volumeRotaryControl = new PwmGpio(10, {
        mode: PwmGpio.INPUT,
        edge: PwmGpio.EITHER_EDGE
    });

    var init = function () {
        // Turn on LED indicating application is running
        appRunningIndicatorLed.writeSync(1);
    };

    var quitHandler = function () {
        debug('Cleaning up our mess.');

        // Clear perhipherals
        appRunningIndicatorLed.unexport();
    };

    btnPlayPause.on('pressed', function () {
        self.emit('playPauseButtonPressed');
    });

    btnPlayPreviousTrack.on('pressed', function () {
        self.emit('playPreviousTrackButtonPressed');
    });

    btnPlayNextTrack.on('pressed', function () {
        self.emit('playNextTrackButtonPressed');
    });

    volumeRotaryControl.on('interrupt', function (level) {
        debug('[VOLUME ROTARY CONTROL] Interrupt!', level);
    });

    // Gracefully exit on CTRL+C and errors
    process.on('forceQuitApplication', quitHandler);

    init();

};

//

// Class inherits EventEmitter so we can dispatch and listen to events on the object itself
util.inherits(Controls, EventEmitter);

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


<commit_before>// eslint-disable react/jsx-indent rule added for proper <Markdown /> formatting
/* eslint-disable react/jsx-indent */
const React = require('react');
const { Link } = require('react-router');

const Code = require('components/Code');
const { DateRangePicker } = require('mx-react-components');

const Markdown = require('components/Markdown');

class DateRangePickerDocs extends React.Component {
  state = {
    selectedEndDate: null,
    selectedStartDate: null
  };

  _handleDateRangeSelect = (selectedStartDate, selectedEndDate) => {
    this.setState({
      selectedStartDate,
      selectedEndDate
    });
  };

  render () {
    return (

          DateRangePicker
          Used to select a date range with a start and end value.

Demo

        <DateRangePicker
          onDateRangeSelect={this._handleDateRangeSelect}
          selectedEndDate={this.state.selectedEndDate}
          selectedStartDate={this.state.selectedStartDate}
          showDefaultRanges={true}
        />

Usage

defaultRanges Array of range option objects

Default: See Code for default array of ranges

Array of default range objects used when showDefaultRanges prop is set to true.  If not supplied, the default above is used.

Range objects consists of a `displayValue` and two functions that get the start and end date. These functions much return unix timestamps

        <Markdown lang='js'>
        {`
          [{
            displayValue: 'Today',
            getEndDate: () => moment.endOf('day').unix(), // These must be a unix timestamp
            getStartDate: () => moment.startOf('day').unix()
          }]
        `}
        </Markdown>

focusTrapPropsObject

Default: Empty Object

The DateRangePicker component uses the Focus Trap React library to prevent a user from tabing outside the date range picker for accessibility reasons.

The focusTrapProps object provides a mechanism for passing the focus trap component props.

See the library documentation for details on what props it accepts and how to use them.

format String

Default: 'MMM D, YYYY'

This is used to determine the format of the selected date. It should follow the Moment.js conventions outlined here.

locale String

Default: 'en'

This is used to format the dates, day names, month names, etc based on the locale.

isRelative boolean

Default: true

Determines if the selected date and options are positioned relative or static.

minimumDate Number (unix timestamp)

If set, the user will not be able to select a date prior to this date.

onDateRangeSelect Function

A function to be called when the user has applied their selected date range. The range's start and end dates are passed as arguements to the call.

onDateSelect Function

A function to be called when the user has selected a date. The selected date timestamp(s) will be passed to this function.

*This prop is deprecated and will be removed in a future release. Please use onDateRangeSelect instead.

placeholderText String

Default: Select A Date

A string used as placeholder text for the selected date input when it is empty.

selectedEndDate Number (unix timestamp)

This sets the selected end date on the component. Can be used to set a default end date.

selectedStartDate Number (unix timestamp)

This sets the selected start date on the component. Can be used to set a default start date.

showDefaultRanges Bool

Default: false

When set to true, shows the default range options.

style Object

Additional styles that can be set on the main wrapping component.

styles Object

A nested object that allows you to set styles on any of the elements in the component. See the `styles` method in the component code for a full list of available keys and values.

theme Object

Customize the component's look. See <Link to='/components/theme'>Theme</Link> for more information.

Example

        <Markdown>
        {`
          _handleDateRangeSelect (selectedStartDate, selectedEndDate) {
            this.setState({
              selectedStartDate,
              selectedEndDate
            });
          },

          <DateRangePicker
            onDateRangeSelect={this._handleDateRangeSelect}
            selectedEndDate={this.state.selectedEndDate}
            selectedStartDate={this.state.selectedStartDate}
            showDefaultRanges={true}
          />
        `}
        </Markdown>

    );
  }
}

module.exports = DateRangePickerDocs;
<commit_msg>Fixes docs for focusTrapProps<commit_after>// eslint-disable react/jsx-indent rule added for proper <Markdown /> formatting
/* eslint-disable react/jsx-indent */
const React = require('react');
const { Link } = require('react-router');

const Code = require('components/Code');
const { DateRangePicker } = require('mx-react-components');

const Markdown = require('components/Markdown');

class DateRangePickerDocs extends React.Component {
  state = {
    selectedEndDate: null,
    selectedStartDate: null
  };

  _handleDateRangeSelect = (selectedStartDate, selectedEndDate) => {
    this.setState({
      selectedStartDate,
      selectedEndDate
    });
  };

  render () {
    return (

          DateRangePicker
          Used to select a date range with a start and end value.

Demo

        <DateRangePicker
          onDateRangeSelect={this._handleDateRangeSelect}
          selectedEndDate={this.state.selectedEndDate}
          selectedStartDate={this.state.selectedStartDate}
          showDefaultRanges={true}
        />

Usage

defaultRanges Array of range option objects

Default: See Code for default array of ranges

Array of default range objects used when showDefaultRanges prop is set to true.  If not supplied, the default above is used.

Range objects consists of a `displayValue` and two functions that get the start and end date. These functions much return unix timestamps

        <Markdown lang='js'>
        {`
          [{
            displayValue: 'Today',
            getEndDate: () => moment.endOf('day').unix(), // These must be a unix timestamp
            getStartDate: () => moment.startOf('day').unix()
          }]
        `}
        </Markdown>

focusTrapPropsObject

Default: Empty Object

The DateRangePicker component uses the Focus Trap React library to prevent a user from tabing outside the date range picker for accessibility reasons.

The focusTrapProps object provides a mechanism for passing the focus trap component props.

See the library documentation for details on what props it accepts and how to use them.

format String

Default: 'MMM D, YYYY'

This is used to determine the format of the selected date. It should follow the Moment.js conventions outlined here.

locale String

Default: 'en'

This is used to format the dates, day names, month names, etc based on the locale.

isRelative boolean

Default: true

Determines if the selected date and options are positioned relative or static.

minimumDate Number (unix timestamp)

If set, the user will not be able to select a date prior to this date.

onDateRangeSelect Function

A function to be called when the user has applied their selected date range. The range's start and end dates are passed as arguements to the call.

onDateSelect Function

A function to be called when the user has selected a date. The selected date timestamp(s) will be passed to this function.

*This prop is deprecated and will be removed in a future release. Please use onDateRangeSelect instead.

placeholderText String

Default: Select A Date

A string used as placeholder text for the selected date input when it is empty.

selectedEndDate Number (unix timestamp)

This sets the selected end date on the component. Can be used to set a default end date.

selectedStartDate Number (unix timestamp)

This sets the selected start date on the component. Can be used to set a default start date.

showDefaultRanges Bool

Default: false

When set to true, shows the default range options.

style Object

Additional styles that can be set on the main wrapping component.

styles Object

A nested object that allows you to set styles on any of the elements in the component. See the `styles` method in the component code for a full list of available keys and values.

theme Object

Customize the component's look. See <Link to='/components/theme'>Theme</Link> for more information.

Example

        <Markdown>
        {`
          _handleDateRangeSelect (selectedStartDate, selectedEndDate) {
            this.setState({
              selectedStartDate,
              selectedEndDate
            });
          },

          <DateRangePicker
            onDateRangeSelect={this._handleDateRangeSelect}
            selectedEndDate={this.state.selectedEndDate}
            selectedStartDate={this.state.selectedStartDate}
            showDefaultRanges={true}
          />
        `}
        </Markdown>

    );
  }
}

module.exports = DateRangePickerDocs;
<|endoftext|>


<commit_before>// ==UserScript==
// @name		TP-LINK Prettifier
// @author		Giuseppe Bertone, Brainmote s.r.l.s.
// @namespace	http://www.brainmote.com
// @version		1.0
// @updateURL   https://raw.githubusercontent.com/Brainmote/TP-Link-Prettifier/master/tp-link-prettifier.user.js
// @downloadURL	https://raw.githubusercontent.com/Brainmote/TP-Link-Prettifier/1.0/tp-link-prettifier.user.js
// @description This script is used to prettify the "Wireless Station Status" page for TP-Link TD-W8970 router. In particular, with this script you can see the description near the MAC address for devices you already registered in the Wireless MAC Filtering page. (you can see a snapshot here https://goo.gl/pBjoLY). Tested on Firmware version: 0.6.0 2.8 v000c.0 Build 130828 Rel.38099n and Hardware version: TD-W8970 v1 00000000
// @match		http://192.168.1.1/*
// @copyright	2014+, Brainmote s.r.l.s.
// @license		Apache License Version 2.0
// @require		https://s3-eu-west-1.amazonaws.com/public.brainmote.com/userscripts/jquery-2.1.1.min.js
// @grant		unsafeWindow
// ==/UserScript==

$(document).ready(
    function() {
        //Modify the original ajax function so I can call the prettify when needed
        unsafeWindow.$.ajaxOriginal = unsafeWindow.$.ajax;
        unsafeWindow.$.ajax = function( s ) {
            if ( "/cgi?7" == s.url ){
                $.when( unsafeWindow.$.ajaxOriginal( s ) ).done( function(){
                    //Use a little timeout to let the list to be loaded
                    setTimeout(
                        function() {
                            //Native call to the router to get the registered mac list
                            unsafeWindow.$.io( "./cgi?5", false, function( response ) {
                                //Read the response and prepare a clean MAC list (key = mac address, value = description)
                                response = response.replace( /X_TPLINK_Description=/g, "" );
                                response = response.replace( /X_TPLINK_MACAddress=/g, "" );
                                var responseArray = response.split( '\n' );
                                var macList = {};
                                for( var i = 2; i < responseArray.length; i+=4 ){
                                    macList[responseArray[i]] = responseArray[i+1];
                                }
                                //Change the table headers widths
                                var largeColumnWidth = "35%";
                                var smallColumnWidth = "20%";
                                var header = $( ".T.T_macaddr" );
                                header.attr( "width", largeColumnWidth );
                                header.text( "Description (MAC Address)" );
                                $( "#t_curstat1" ).attr( "width", smallColumnWidth );
                                $( "#t_rxpkts1" ).attr( "width", smallColumnWidth );
                                //List all MAC addresses and show description
                                $( "td[width='20%']" ).each( function( index, element ) {
                                    element.width = largeColumnWidth;
                                    if ( macList[element.innerHTML] ) {
                                        element.innerHTML = macList[element.innerHTML] + " (" + element.innerHTML + ")";
                                    }
                                });
                                //Modify widths of other tds
                                $( "td[width='25%']" ).each( function( index, element ) { element.width = smallColumnWidth; });
                            }, "[LAN_WLAN_MACTABLEENTRY#0,0,0,0,0,0#1,1,0,0,0,0]0,3\r\nX_TPLINK_Enabled\r\nX_TPLINK_MACAddress\r\nX_TPLINK_Description\r\n", false );
                        }, 250 );});
            } else {
                unsafeWindow.$.ajaxOriginal( s );
            }
        }
    });
<commit_msg>Update tp-link-prettifier.user.js<commit_after>// ==UserScript==
// @name		TP-LINK Prettifier
// @author		Giuseppe Bertone, Brainmote s.r.l.s.
// @namespace	http://www.brainmote.com
// @version		1.0
// @updateURL   https://raw.githubusercontent.com/Brainmote/TP-Link-Prettifier/master/tp-link-prettifier.user.js
// @downloadURL	https://raw.githubusercontent.com/Brainmote/TP-Link-Prettifier/1.0-release/tp-link-prettifier.user.js
// @description This script is used to prettify the "Wireless Station Status" page for TP-Link TD-W8970 router. In particular, with this script you can see the description near the MAC address for devices you already registered in the Wireless MAC Filtering page. (you can see a snapshot here https://goo.gl/pBjoLY). Tested on Firmware version: 0.6.0 2.8 v000c.0 Build 130828 Rel.38099n and Hardware version: TD-W8970 v1 00000000
// @match		http://192.168.1.1/*
// @copyright	2014+, Brainmote s.r.l.s.
// @license		Apache License Version 2.0
// @require		https://s3-eu-west-1.amazonaws.com/public.brainmote.com/userscripts/jquery-2.1.1.min.js
// @grant		unsafeWindow
// ==/UserScript==

$(document).ready(
    function() {
        //Modify the original ajax function so I can call the prettify when needed
        unsafeWindow.$.ajaxOriginal = unsafeWindow.$.ajax;
        unsafeWindow.$.ajax = function( s ) {
            if ( "/cgi?7" == s.url ){
                $.when( unsafeWindow.$.ajaxOriginal( s ) ).done( function(){
                    //Use a little timeout to let the list to be loaded
                    setTimeout(
                        function() {
                            //Native call to the router to get the registered mac list
                            unsafeWindow.$.io( "./cgi?5", false, function( response ) {
                                //Read the response and prepare a clean MAC list (key = mac address, value = description)
                                response = response.replace( /X_TPLINK_Description=/g, "" );
                                response = response.replace( /X_TPLINK_MACAddress=/g, "" );
                                var responseArray = response.split( '\n' );
                                var macList = {};
                                for( var i = 2; i < responseArray.length; i+=4 ){
                                    macList[responseArray[i]] = responseArray[i+1];
                                }
                                //Change the table headers widths
                                var largeColumnWidth = "35%";
                                var smallColumnWidth = "20%";
                                var header = $( ".T.T_macaddr" );
                                header.attr( "width", largeColumnWidth );
                                header.text( "Description (MAC Address)" );
                                $( "#t_curstat1" ).attr( "width", smallColumnWidth );
                                $( "#t_rxpkts1" ).attr( "width", smallColumnWidth );
                                //List all MAC addresses and show description
                                $( "td[width='20%']" ).each( function( index, element ) {
                                    element.width = largeColumnWidth;
                                    if ( macList[element.innerHTML] ) {
                                        element.innerHTML = macList[element.innerHTML] + " (" + element.innerHTML + ")";
                                    }
                                });
                                //Modify widths of other tds
                                $( "td[width='25%']" ).each( function( index, element ) { element.width = smallColumnWidth; });
                            }, "[LAN_WLAN_MACTABLEENTRY#0,0,0,0,0,0#1,1,0,0,0,0]0,3\r\nX_TPLINK_Enabled\r\nX_TPLINK_MACAddress\r\nX_TPLINK_Description\r\n", false );
                        }, 250 );});
            } else {
                unsafeWindow.$.ajaxOriginal( s );
            }
        }
    });
<|endoftext|>


<commit_before>/*jshint esversion: 6 */
/* globals console, require*/
'use strict';
// Load required libraries
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamodb = new AWS.DynamoDB.DocumentClient();
const moment = require('moment-timezone');

exports.handler = (event, context, callback) => {

  let startTime;
  // If there is a lastupdated parameter, scan from that time
  if (Number(event.lastupdated) > 1) {
    console.log('Detecting lastupdated variable, ' + event.lastupdated);
    startTime = Number(event.lastupdated);
  } else {
    startTime = 1;
  }

  // Set scan limit to 20 if not present or greater than 20
  let limit = 20;
  if (Number(event.limit) < 20) {
    limit = event.limit;
  }

  console.log('Scanning from greater than ' + startTime);
  // Set scanning parameters
  let params = {
    TableName: 'impact-map',
    // Only get Coordinates and Action data from the table
    ProjectionExpression: 'Coordinates, #b',
    // Only return items that have an Added time that is greater than startTime
    FilterExpression: 'Added > :start',
    ExpressionAttributeNames: {
      // Set an 'alias' for the word, 'Action', because 'Action' is a reserved word in DynamoDB
      '#b': 'Action'
    },
    ExpressionAttributeValues: {
      // Set an 'alias' for startTime, called ':start'
      ':start': startTime
    },
    Limit: limit
  };

  if (typeof event.lastevaluatedkey != 'undefined') {
    params.LastEvaluatedKey = event.lastevaluatedkey;
  }

  console.log('Scanning table.');
  dynamodb.scan(params, onScan);

  function onScan(err, data) {
    // Log error if scanning returns err
    if (err) {
      console.error('Unable to scan the table. Error JSON:', JSON.stringify(err, null, 2));
    } else {
      console.log('Scan succeeded.');
      // Continue scanning if we have more items, because scan can retrieve a maximum of 1MB of data
      if (typeof data.LastEvaluatedKey != 'undefined') {
        console.log('LastEvaluatedKey detected');
      }
      // Returns the item data back to the client
      console.log('Returning ' + data.length + ' items to the client');
      callback(null, data);
    }
  }
};
<commit_msg>Add exports to JShint variables list<commit_after>/*jshint esversion: 6 */
/* globals console, require, exports*/
'use strict';
// Load required libraries
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
const dynamodb = new AWS.DynamoDB.DocumentClient();
const moment = require('moment-timezone');

exports.handler = (event, context, callback) => {

  let startTime;
  // If there is a lastupdated parameter, scan from that time
  if (Number(event.lastupdated) > 1) {
    console.log('Detecting lastupdated variable, ' + event.lastupdated);
    startTime = Number(event.lastupdated);
  } else {
    startTime = 1;
  }

  // Set scan limit to 20 if not present or greater than 20
  let limit = 20;
  if (Number(event.limit) < 20) {
    limit = event.limit;
  }

  console.log('Scanning from greater than ' + startTime);
  // Set scanning parameters
  let params = {
    TableName: 'impact-map',
    // Only get Coordinates and Action data from the table
    ProjectionExpression: 'Coordinates, #b',
    // Only return items that have an Added time that is greater than startTime
    FilterExpression: 'Added > :start',
    ExpressionAttributeNames: {
      // Set an 'alias' for the word, 'Action', because 'Action' is a reserved word in DynamoDB
      '#b': 'Action'
    },
    ExpressionAttributeValues: {
      // Set an 'alias' for startTime, called ':start'
      ':start': startTime
    },
    Limit: limit
  };

  if (typeof event.lastevaluatedkey != 'undefined') {
    params.LastEvaluatedKey = event.lastevaluatedkey;
  }

  console.log('Scanning table.');
  dynamodb.scan(params, onScan);

  function onScan(err, data) {
    // Log error if scanning returns err
    if (err) {
      console.error('Unable to scan the table. Error JSON:', JSON.stringify(err, null, 2));
    } else {
      console.log('Scan succeeded.');
      // Continue scanning if we have more items, because scan can retrieve a maximum of 1MB of data
      if (typeof data.LastEvaluatedKey != 'undefined') {
        console.log('LastEvaluatedKey detected');
      }
      // Returns the item data back to the client
      console.log('Returning ' + data.length + ' items to the client');
      callback(null, data);
    }
  }
};
<|endoftext|>


<commit_before>import { Mongo } from 'meteor/mongo';

export const Rooms = new Meteor.Collection("rooms",
{
    transform:function(entry)
    {
        entry.goLeft = function(){ return(undefined);};
        entry.goRight = function(){ return(undefined);};
        entry.goForward = function(direction){
          return(this.passages[direction]);
        };
        entry.toString = function(){
          return(this.x.toString() + "," + this.y.toString());
        };
        return entry;
    }
});
<commit_msg>get right direction<commit_after>import { Mongo } from 'meteor/mongo';

export const Rooms = new Meteor.Collection("rooms",
{
    transform:function(entry)
    {
        entry.getRightDirection = function(direction) {
          switch (direction) {
          case 'N':
            return('E');
          case 'E':
            return('S');
          case 'S':
            return('W');
          default:
            return('N');
          }
        };
        entry.goLeft = function(){ return(undefined);};
        entry.goRight = function(direction) {
          return(this.passages[this.getRightDirection(direction)]);
        };
        entry.goForward = function(direction) {
          return(this.passages[direction]);
        };
        entry.toString = function() {
          return(this.x.toString() + "," + this.y.toString());
        };
        return entry;
    }
});
<|endoftext|>


<commit_before>// @flow
import * as React from 'react';
import classNames from 'classnames';
import _ from 'lodash';
import { DOMMouseMoveTracker, addStyle, getOffset, translateDOMPositionXY } from 'dom-lib';
import { SCROLLBAR_MIN_WIDTH } from './constants';
import { defaultClassPrefix, getUnhandledProps, prefix } from './utils';

type Props = {
  vertical?: boolean,
  length: number,
  scrollLength: number,
  className?: string,
  classPrefix?: string,
  onScroll?: Function,
  onMouseDown?: Function
};

type Offset = {
  top: number,
  left: number,
  height?: number,
  width?: number
};

type State = {
  barOffset: Offset,
  handlePressed: boolean
};

class Scrollbar extends React.PureComponent<Props, State> {
  static defaultProps = {
    classPrefix: defaultClassPrefix('table-scrollbar'),
    scrollLength: 1,
    length: 1
  };

  constructor(props: Props) {
    super(props);
    this.state = {
      barOffset: {
        top: 0,
        left: 0
      },
      handlePressed: false
    };
  }

  componentDidMount() {
    this.initBarOffset();
  }

  componentWillUnmount() {
    this.releaseMouseMoves();
  }

  onWheelScroll(delta: number) {
    const { length, scrollLength } = this.props;
    const nextDelta = delta / (scrollLength / length);

    this.updateScrollBarPosition(nextDelta);
  }

  getMouseMoveTracker() {
    return (
      this.mouseMoveTracker ||
      new DOMMouseMoveTracker(this.hanldeDragMove, this.hanldeDragEnd, document.body)
    );
  }

  initBarOffset() {
    setTimeout(() => {
      this.bar &&
        this.setState({
          barOffset: getOffset(this.bar)
        });
    }, 1);
  }

  hanldeMouseDown = (event: SyntheticMouseEvent<*>) => {
    const { onMouseDown } = this.props;

    this.mouseMoveTracker = this.getMouseMoveTracker();
    this.mouseMoveTracker.captureMouseMoves(event);
    this.setState({
      handlePressed: true
    });
    onMouseDown && onMouseDown(event);
  };

  hanldeDragEnd = () => {
    this.releaseMouseMoves();
    this.setState({
      handlePressed: false
    });
  };

  handleScroll(delta: number, event: SyntheticEvent<*>) {
    const { length, scrollLength, onScroll } = this.props;
    const scrollDelta = delta * (scrollLength / length);

    this.updateScrollBarPosition(delta);
    onScroll && onScroll(scrollDelta, event);
  }

  resetScrollBarPosition(forceDelta: number = 0) {
    this.scrollOffset = 0;
    this.updateScrollBarPosition(0, forceDelta);
  }

  updateScrollBarPosition(delta: number, forceDelta?: number) {
    const { vertical, length, scrollLength } = this.props;
    const max = scrollLength && length ? length - (length / scrollLength) * length : 0;
    const styles = {};

    if (_.isUndefined(forceDelta)) {
      this.scrollOffset += delta;
      this.scrollOffset = Math.max(this.scrollOffset, 0);
      this.scrollOffset = Math.min(this.scrollOffset, max);
    } else {
      this.scrollOffset = forceDelta || 0;
    }

    if (vertical) {
      translateDOMPositionXY(styles, 0, this.scrollOffset);
    } else {
      translateDOMPositionXY(styles, this.scrollOffset, 0);
    }

    addStyle(this.handle, styles);
  }

  releaseMouseMoves() {
    if (this.mouseMoveTracker) {
      this.mouseMoveTracker.releaseMouseMoves();
      this.mouseMoveTracker = null;
    }
  }

  hanldeDragMove = (deltaX: number, deltaY: number, event: SyntheticEvent<*>) => {
    const { vertical } = this.props;

    if (!this.mouseMoveTracker || !this.mouseMoveTracker.isDragging()) {
      return;
    }
    this.handleScroll(vertical ? deltaY : deltaX, event);
  };

  /**
   * 点击滚动条，然后滚动到指定位置
   */
  hanldeClick = (event: SyntheticMouseEvent<*>) => {
    if (this.handle && this.handle.contains(event.target)) {
      return;
    }

    const { vertical, length, scrollLength } = this.props;
    const { barOffset } = this.state;
    const offset = vertical ? event.pageY - barOffset.top : event.pageX - barOffset.left;

    const handleWidth = (length / scrollLength) * length;
    const delta = offset - handleWidth;

    const nextDelta =
      offset > this.scrollOffset ? delta - this.scrollOffset : offset - this.scrollOffset;
    this.handleScroll(nextDelta, event);
  };

  scrollOffset: number = 0;
  mouseMoveTracker: any;
  handle: any;
  bar: any;

  bindBarRef = (ref: React.ElementRef<*>) => {
    this.bar = ref;
  };

  bindHandleRef = (ref: React.ElementRef<*>) => {
    this.handle = ref;
  };

  render() {
    const { vertical, length, scrollLength, classPrefix, className, ...rest } = this.props;
    const { handlePressed } = this.state;
    const addPrefix = prefix(classPrefix);
    const classes = classNames(classPrefix, className, {
      [addPrefix('vertical')]: vertical,
      [addPrefix('horizontal')]: !vertical,
      [addPrefix('hide')]: scrollLength <= length,
      [addPrefix('pressed')]: handlePressed
    });

    let styles = {
      [vertical ? 'height' : 'width']: `${(length / scrollLength) * 100}%`,
      [vertical ? 'minHeight' : 'minWidth']: SCROLLBAR_MIN_WIDTH
    };
    const unhandled = getUnhandledProps(Scrollbar, rest);

    return (
      <div
        {...unhandled}
        ref={this.bindBarRef}
        className={classes}
        onClick={this.hanldeClick}
        role="toolbar"
      >
        <div
          ref={this.bindHandleRef}
          className={addPrefix('handle')}
          style={styles}
          onMouseDown={this.hanldeMouseDown}
          role="button"
          tabIndex={-1}
        />
      </div>
    );
  }
}

export default Scrollbar;
<commit_msg>Fix scrollbar position<commit_after>// @flow
import * as React from 'react';
import classNames from 'classnames';
import _ from 'lodash';
import { DOMMouseMoveTracker, addStyle, getOffset, translateDOMPositionXY } from 'dom-lib';
import { SCROLLBAR_MIN_WIDTH } from './constants';
import { defaultClassPrefix, getUnhandledProps, prefix } from './utils';

type Props = {
  vertical?: boolean,
  length: number,
  scrollLength: number,
  className?: string,
  classPrefix?: string,
  onScroll?: Function,
  onMouseDown?: Function
};

type Offset = {
  top: number,
  left: number,
  height?: number,
  width?: number
};

type State = {
  barOffset: Offset,
  handlePressed: boolean
};

class Scrollbar extends React.PureComponent<Props, State> {
  static defaultProps = {
    classPrefix: defaultClassPrefix('table-scrollbar'),
    scrollLength: 1,
    length: 1
  };

  constructor(props: Props) {
    super(props);
    this.state = {
      barOffset: {
        top: 0,
        left: 0
      },
      handlePressed: false
    };
  }

  componentDidMount() {
    this.initBarOffset();
  }

  componentWillUnmount() {
    this.releaseMouseMoves();
  }

  onWheelScroll(delta: number) {
    const { length, scrollLength } = this.props;
    const nextDelta = delta / (scrollLength / length);

    this.updateScrollBarPosition(nextDelta);
  }

  getMouseMoveTracker() {
    return (
      this.mouseMoveTracker ||
      new DOMMouseMoveTracker(this.hanldeDragMove, this.hanldeDragEnd, document.body)
    );
  }

  initBarOffset() {
    setTimeout(() => {
      this.bar &&
        this.setState({
          barOffset: getOffset(this.bar)
        });
    }, 1);
  }

  hanldeMouseDown = (event: SyntheticMouseEvent<*>) => {
    const { onMouseDown } = this.props;

    this.mouseMoveTracker = this.getMouseMoveTracker();
    this.mouseMoveTracker.captureMouseMoves(event);
    this.setState({
      handlePressed: true
    });
    onMouseDown && onMouseDown(event);
  };

  hanldeDragEnd = () => {
    this.releaseMouseMoves();
    this.setState({
      handlePressed: false
    });
  };

  handleScroll(delta: number, event: SyntheticEvent<*>) {
    const { length, scrollLength, onScroll } = this.props;
    const scrollDelta = delta * (scrollLength / length);

    this.updateScrollBarPosition(delta);
    onScroll && onScroll(scrollDelta, event);
  }

  resetScrollBarPosition(forceDelta: number = 0) {
    this.scrollOffset = 0;
    this.updateScrollBarPosition(0, forceDelta);
  }

  updateScrollBarPosition(delta: number, forceDelta?: number) {
    const { vertical, length, scrollLength } = this.props;
    const max =
      scrollLength && length
        ? length - Math.max((length / scrollLength) * length, SCROLLBAR_MIN_WIDTH + 2)
        : 0;
    const styles = {};

    if (_.isUndefined(forceDelta)) {
      this.scrollOffset += delta;
      this.scrollOffset = Math.max(this.scrollOffset, 0);
      this.scrollOffset = Math.min(this.scrollOffset, max);
    } else {
      this.scrollOffset = forceDelta || 0;
    }

    if (vertical) {
      translateDOMPositionXY(styles, 0, this.scrollOffset);
    } else {
      translateDOMPositionXY(styles, this.scrollOffset, 0);
    }

    addStyle(this.handle, styles);
  }

  releaseMouseMoves() {
    if (this.mouseMoveTracker) {
      this.mouseMoveTracker.releaseMouseMoves();
      this.mouseMoveTracker = null;
    }
  }

  hanldeDragMove = (deltaX: number, deltaY: number, event: SyntheticEvent<*>) => {
    const { vertical } = this.props;

    if (!this.mouseMoveTracker || !this.mouseMoveTracker.isDragging()) {
      return;
    }
    this.handleScroll(vertical ? deltaY : deltaX, event);
  };

  /**
   * 点击滚动条，然后滚动到指定位置
   */
  hanldeClick = (event: SyntheticMouseEvent<*>) => {
    if (this.handle && this.handle.contains(event.target)) {
      return;
    }

    const { vertical, length, scrollLength } = this.props;
    const { barOffset } = this.state;
    const offset = vertical ? event.pageY - barOffset.top : event.pageX - barOffset.left;

    const handleWidth = (length / scrollLength) * length;
    const delta = offset - handleWidth;

    const nextDelta =
      offset > this.scrollOffset ? delta - this.scrollOffset : offset - this.scrollOffset;
    this.handleScroll(nextDelta, event);
  };

  scrollOffset: number = 0;
  mouseMoveTracker: any;
  handle: any;
  bar: any;

  bindBarRef = (ref: React.ElementRef<*>) => {
    this.bar = ref;
  };

  bindHandleRef = (ref: React.ElementRef<*>) => {
    this.handle = ref;
  };

  render() {
    const { vertical, length, scrollLength, classPrefix, className, ...rest } = this.props;
    const { handlePressed } = this.state;
    const addPrefix = prefix(classPrefix);
    const classes = classNames(classPrefix, className, {
      [addPrefix('vertical')]: vertical,
      [addPrefix('horizontal')]: !vertical,
      [addPrefix('hide')]: scrollLength <= length,
      [addPrefix('pressed')]: handlePressed
    });

    let styles = {
      [vertical ? 'height' : 'width']: `${(length / scrollLength) * 100}%`,
      [vertical ? 'minHeight' : 'minWidth']: SCROLLBAR_MIN_WIDTH
    };
    const unhandled = getUnhandledProps(Scrollbar, rest);

    return (
      <div
        {...unhandled}
        ref={this.bindBarRef}
        className={classes}
        onClick={this.hanldeClick}
        role="toolbar"
      >
        <div
          ref={this.bindHandleRef}
          className={addPrefix('handle')}
          style={styles}
          onMouseDown={this.hanldeMouseDown}
          role="button"
          tabIndex={-1}
        />
      </div>
    );
  }
}

export default Scrollbar;
<|endoftext|>