<commit_before>/***
 * A standalone touch library for mobile devices.
 * @author rainyjune <rainyjune@live.cn>
 */

/* global define, Zepto */
((function(){

  function TouchObject(domElement) {
    this.element = domElement;
    // Put all TouchEvent objects fired in the touchstart event into this array.
    var touchStartTouchList = [];

    var elementListeners= [];

    this.__defineGetter__("touchStartTouchList", function() {
      return touchStartTouchList;
    });
    this.__defineGetter__("elementListeners", function() {
      return elementListeners;
    });

    var isTapLength,
        tapLengthTimeout;

    this.horizontalOffset = 20,
    this.verticalOffset = 30;

    this.isDebug = true;

    this.bindEvents();
  }

  TouchObject.prototype.bindMouseEvents = function() {
    var element = this.element;

    var mouseStartHandlerBind = mousestartHandler.bind(this);
    var mousemoveHandlerBind = mousemoveHandler.bind(this);
    var mouseEndHandlerBind = mouseEndHandler.bind(this);

    element.addEventListener("mousedown", mouseStartHandlerBind, false);
    element.addEventListener("mousemove", mousemoveHandlerBind, false);
    element.addEventListener("mouseup", mouseEndHandlerBind, false);
    element.addEventListener("mouseleave", mouseEndHandlerBind, false);

    this.elementListeners.push({
      "eventName": "mousedown",
      "callback": mouseStartHandlerBind
    });
    this.elementListeners.push({
      "eventName": "mousemove",
      "callback": mousemoveHandlerBind
    });
    this.elementListeners.push({
      "eventName": "mouseup",
      "callback": mouseEndHandlerBind
    });
    this.elementListeners.push({
      "eventName": "mouseleave",
      "callback": mouseEndHandlerBind
    });

    function mousestartHandler(event) {
      var touchCopy = this.copyTouch(event);
      this.touchStartTouchList.push(touchCopy);
      this.trigger("swipeStart", event);
    }

    function mousemoveHandler(event) {
      // The 'touch' event not started.
      if (this.touchStartTouchList.length === 0) {
        return false;
      }
      var firstTouchStartEvent = this.touchStartTouchList[0];
      var nowPageX = event.pageX;
      var nowPageY = event.pageY;
      var movedPageX = nowPageX - firstTouchStartEvent.pageX;
      var movedPageY = nowPageY - firstTouchStartEvent.pageY;
      var eventObj = {
        pageX: event.pageX,
        pageY: event.pageY,
        clientX: event.clientX,
        clientY: event.clientY,
        screenX: event.screenX,
        screenY: event.screenY,
        detail: {'movedPageX': movedPageX, 'movedPageY': movedPageY}
      };
      this.trigger("swipeProgress", eventObj);
    }

    function mouseEndHandler(event) {
      var firstTouchStartEvent = this.touchStartTouchList[0];
      if (!firstTouchStartEvent) {
        return false;
      }
      this.touchStartTouchList.length = 0;

      var touchX = firstTouchStartEvent.clientX,
          nowX = event.clientX,
          touchY = firstTouchStartEvent.clientY,
          nowY = event.clientY;

      var movX = Math.abs(touchX - nowX);
      var movY = Math.abs(touchY - nowY);

      if (movX > this.horizontalOffset || movY > this.verticalOffset) {
        this.trigger("swipe", event);
        var direction = swipeDirection(touchX, nowX, touchY, nowY);
        this.trigger("swipe" + direction, event);
      } else {
        this.trigger("swipeCancel", event);
      }
    }

  };

  TouchObject.prototype.bindPointerEvents = function() {
    var pointerDownName = window.PointerEvent ? "pointerdown" : "MSPointerDown",
        pointerMoveName = window.PointerEvent ? "pointermove" : "MSPointerMove",
        pointerUpName = window.PointerEvent ? "pointerup" : "MSPointerUp",
        pointerCancelName = window.PointerEvent ? "pointercancel" : "MSPointerCancel";

    var pointerDownBind = pointerDown.bind(this),
        pointerMoveBind = pointerMove.bind(this),
        pointerUpBind = pointerUp.bind(this),
        pointerCancelBind = pointerCancel.bind(this);

    var element = this.element,
        elementListeners = this.elementListeners;

    element.addEventListener(pointerDownName, pointerDownBind, false);
    element.addEventListener(pointerMoveName, pointerMoveBind, false);
    element.addEventListener(pointerUpName, pointerUpBind, false);
    element.addEventListener(pointerCancelName, pointerCancelBind, false);

    elementListeners.push({ "eventName": pointerDownName, "callback":  pointerDownBind });
    elementListeners.push({ "eventName": pointerMoveName, "callback": pointerMoveBind });
    elementListeners.push({ "eventName": pointerUpName, "callback": pointerUpBind });
    elementListeners.push({ "eventName": pointerCancelName, "callback": pointerCancelBind });

    function pointerDown(event) {
      var touchCopy = this.copyTouch(event);
      this.touchStartTouchList.push(touchCopy);
      this.trigger("swipeStart", event);
    }

    function pointerMove(event) {

    }

    function pointerUp(event) {

    }

    function pointerCancel(event) {

    }

  };

  TouchObject.prototype.copyTouch = function(touch) {
    return {
      "identifier": touch.identifier || touch.pointerId || 0,
      "pageX": touch.pageX,
      "pageY": touch.pageY,
      "clientX": touch.clientX,
      "clientY": touch.clientY,
      "screenX": touch.screenX,
      "screenY": touch.screenY
    };
  };

  TouchObject.prototype.bindEvents = function() {
    if (window.PointerEvent || window.navigator.msPointerEnabled) {
      this.bindPointerEvents();
    } else if (('ontouchstart' in document.documentElement) || ('ontouchstart' in window)){
      this.bindTouchEvents();
    } else {
      this.bindMouseEvents();
    }
  };

  TouchObject.prototype.addEventListener = function(eventName, callback) {
    EventsObject.on(eventName, callback);
  }

  TouchObject.prototype.trigger = function(eventName, customData) {
    EventsObject.trigger(eventName, customData);
  }

  TouchObject.prototype.dispose = function() {
    for (var i = 0; i < this.elementListeners.length; i ++) {
      var currentListener = this.elementListeners[i];
      this.element.removeEventListener(currentListener["eventName"], currentListener["callback"]);
    }
    this.elementListeners.length = 0;
  };

  function swipeDirection(x1, x2, y1, y2) {
    return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down');
  }

  var EventsObject = (function(){
    // Events on and off
    var Events = [];

    function on(event, callback) {
        if (!Events[event]) {
            Events[event] = [];
        }
        Events[event].push(callback);
        return callback;
    }

    function off(event, callback) {
        if (!Events[event]) {
            return ;
        }
        if (callback) {
            var index = Events[event].indexOf(callback);
            if (index !== -1) {
                Events[event].splice(index, 1);
            }
        } else {
            Events[event] = [];
        }
    }

    function trigger (event) {
        if (!Events[event]) {
            return ;
        }
        var args = Array.prototype.slice.call(arguments, 1);
        var callbackArray = Events[event];
        for (var i = callbackArray.length - 1; i >= 0; i--) {
            callbackArray[i].apply(callbackArray[i], args);
        }
    }
    return {
      "on": on,
      "off": off,
      "trigger": trigger
    }
  })();

  if (typeof define === "function" && (define.amd || define.cmd)) {
    define(function(){
      return TouchObject;
    });
  } else {
    window.TouchObject = TouchObject;
  }

})());<commit_msg>Add comments<commit_after>/***
 * A standalone touch library for mobile devices.
 * @author rainyjune <rainyjune@live.cn>
 */

/* global define, Zepto */
((function(){

  function TouchObject(domElement) {
    this.element = domElement;
    // Put all TouchEvent objects fired in the touchstart event into this array.
    var touchStartTouchList = [];

    var elementListeners= [];

    this.__defineGetter__("touchStartTouchList", function() {
      return touchStartTouchList;
    });
    this.__defineGetter__("elementListeners", function() {
      return elementListeners;
    });

    var isTapLength,
        tapLengthTimeout;

    this.horizontalOffset = 20,
    this.verticalOffset = 30;

    this.isDebug = true;

    this.bindEvents();
  }

  TouchObject.prototype.bindMouseEvents = function() {
    var element = this.element;

    var mouseStartHandlerBind = mousestartHandler.bind(this);
    var mousemoveHandlerBind = mousemoveHandler.bind(this);
    var mouseEndHandlerBind = mouseEndHandler.bind(this);

    element.addEventListener("mousedown", mouseStartHandlerBind, false);
    element.addEventListener("mousemove", mousemoveHandlerBind, false);
    element.addEventListener("mouseup", mouseEndHandlerBind, false);
    element.addEventListener("mouseleave", mouseEndHandlerBind, false);

    this.elementListeners.push({
      "eventName": "mousedown",
      "callback": mouseStartHandlerBind
    });
    this.elementListeners.push({
      "eventName": "mousemove",
      "callback": mousemoveHandlerBind
    });
    this.elementListeners.push({
      "eventName": "mouseup",
      "callback": mouseEndHandlerBind
    });
    this.elementListeners.push({
      "eventName": "mouseleave",
      "callback": mouseEndHandlerBind
    });

    function mousestartHandler(event) {
      var touchCopy = this.copyTouch(event);
      this.touchStartTouchList.push(touchCopy);
      this.trigger("swipeStart", event);
    }

    function mousemoveHandler(event) {
      // The 'touch' event not started.
      if (this.touchStartTouchList.length === 0) {
        return false;
      }
      var firstTouchStartEvent = this.touchStartTouchList[0];
      var nowPageX = event.pageX;
      var nowPageY = event.pageY;
      var movedPageX = nowPageX - firstTouchStartEvent.pageX;
      var movedPageY = nowPageY - firstTouchStartEvent.pageY;
      var eventObj = {
        pageX: event.pageX,
        pageY: event.pageY,
        clientX: event.clientX,
        clientY: event.clientY,
        screenX: event.screenX,
        screenY: event.screenY,
        detail: {'movedPageX': movedPageX, 'movedPageY': movedPageY}
      };
      this.trigger("swipeProgress", eventObj);
    }

    function mouseEndHandler(event) {
      var firstTouchStartEvent = this.touchStartTouchList[0];
      if (!firstTouchStartEvent) {
        return false;
      }
      this.touchStartTouchList.length = 0;

      var touchX = firstTouchStartEvent.clientX,
          nowX = event.clientX,
          touchY = firstTouchStartEvent.clientY,
          nowY = event.clientY;

      var movX = Math.abs(touchX - nowX);
      var movY = Math.abs(touchY - nowY);

      if (movX > this.horizontalOffset || movY > this.verticalOffset) {
        this.trigger("swipe", event);
        var direction = swipeDirection(touchX, nowX, touchY, nowY);
        this.trigger("swipe" + direction, event);
      } else {
        this.trigger("swipeCancel", event);
      }
    }

  };

  TouchObject.prototype.bindPointerEvents = function() {
    var pointerDownName = window.PointerEvent ? "pointerdown" : "MSPointerDown",
        pointerMoveName = window.PointerEvent ? "pointermove" : "MSPointerMove",
        pointerUpName = window.PointerEvent ? "pointerup" : "MSPointerUp",
        pointerCancelName = window.PointerEvent ? "pointercancel" : "MSPointerCancel";

    var pointerDownBind = pointerDown.bind(this),
        pointerMoveBind = pointerMove.bind(this),
        pointerUpBind = pointerUp.bind(this),
        pointerCancelBind = pointerCancel.bind(this);

    var element = this.element,
        elementListeners = this.elementListeners;

    element.addEventListener(pointerDownName, pointerDownBind, false);
    element.addEventListener(pointerMoveName, pointerMoveBind, false);
    element.addEventListener(pointerUpName, pointerUpBind, false);
    element.addEventListener(pointerCancelName, pointerCancelBind, false);

    elementListeners.push({ "eventName": pointerDownName, "callback":  pointerDownBind });
    elementListeners.push({ "eventName": pointerMoveName, "callback": pointerMoveBind });
    elementListeners.push({ "eventName": pointerUpName, "callback": pointerUpBind });
    elementListeners.push({ "eventName": pointerCancelName, "callback": pointerCancelBind });

    function pointerDown(event) {
      // event.changedTouches is undefined in IE 11.
      // If there are several touch points at the same time, each of them will fire
      // the pointerdown event individually.
      var touchCopy = this.copyTouch(event);
      this.touchStartTouchList.push(touchCopy);
      this.trigger("swipeStart", event);
    }

    function pointerMove(event) {

    }

    function pointerUp(event) {

    }

    function pointerCancel(event) {

    }

  };

  TouchObject.prototype.copyTouch = function(touch) {
    return {
      "identifier": touch.identifier || touch.pointerId || 0,
      "pageX": touch.pageX,
      "pageY": touch.pageY,
      "clientX": touch.clientX,
      "clientY": touch.clientY,
      "screenX": touch.screenX,
      "screenY": touch.screenY
    };
  };

  TouchObject.prototype.bindEvents = function() {
    if (window.PointerEvent || window.navigator.msPointerEnabled) {
      this.bindPointerEvents();
    } else if (('ontouchstart' in document.documentElement) || ('ontouchstart' in window)){
      this.bindTouchEvents();
    } else {
      this.bindMouseEvents();
    }
  };

  TouchObject.prototype.addEventListener = function(eventName, callback) {
    EventsObject.on(eventName, callback);
  }

  TouchObject.prototype.trigger = function(eventName, customData) {
    EventsObject.trigger(eventName, customData);
  }

  TouchObject.prototype.dispose = function() {
    for (var i = 0; i < this.elementListeners.length; i ++) {
      var currentListener = this.elementListeners[i];
      this.element.removeEventListener(currentListener["eventName"], currentListener["callback"]);
    }
    this.elementListeners.length = 0;
  };

  function swipeDirection(x1, x2, y1, y2) {
    return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down');
  }

  var EventsObject = (function(){
    // Events on and off
    var Events = [];

    function on(event, callback) {
        if (!Events[event]) {
            Events[event] = [];
        }
        Events[event].push(callback);
        return callback;
    }

    function off(event, callback) {
        if (!Events[event]) {
            return ;
        }
        if (callback) {
            var index = Events[event].indexOf(callback);
            if (index !== -1) {
                Events[event].splice(index, 1);
            }
        } else {
            Events[event] = [];
        }
    }

    function trigger (event) {
        if (!Events[event]) {
            return ;
        }
        var args = Array.prototype.slice.call(arguments, 1);
        var callbackArray = Events[event];
        for (var i = callbackArray.length - 1; i >= 0; i--) {
            callbackArray[i].apply(callbackArray[i], args);
        }
    }
    return {
      "on": on,
      "off": off,
      "trigger": trigger
    }
  })();

  if (typeof define === "function" && (define.amd || define.cmd)) {
    define(function(){
      return TouchObject;
    });
  } else {
    window.TouchObject = TouchObject;
  }

})());<|endoftext|>


<commit_before>/*!
Copyright (c) 2014 Dominik Moritz

This file is part of the leaflet locate control. It is licensed under the MIT license.
You can find the project at: https://github.com/domoritz/leaflet-locatecontrol
*/
(function (factory, window) {
     // see https://github.com/Leaflet/Leaflet/blob/master/PLUGIN-GUIDE.md#module-loaders
     // for details on how to structure a leaflet plugin.

    // define an AMD module that relies on 'leaflet'
    if (typeof define === 'function' && define.amd) {
        define(['leaflet'], factory);

    // define a Common JS module that relies on 'leaflet'
    } else if (typeof exports === 'object') {
        module.exports = factory(require('leaflet'));
    }

    // attach your plugin to the global 'L' variable
    if(typeof window !== 'undefined' && window.L){
        window.L.Locate = factory(L);
    }

} (function (L){
    L.Control.Locate = L.Control.extend({
        options: {
            position: 'topleft',
            drawCircle: true,
            follow: false,  // follow with zoom and pan the user's location
            stopFollowingOnDrag: false, // if follow is true, stop following when map is dragged (deprecated)
            // if true locate control remains active on click even if the user's location is in view.
            // clicking control will just pan to location
            remainActive: false,
            markerClass: L.circleMarker, // L.circleMarker or L.marker
            // range circle
            circleStyle: {
                color: '#136AEC',
                fillColor: '#136AEC',
                fillOpacity: 0.15,
                weight: 2,
                opacity: 0.5
            },
            // inner marker
            markerStyle: {
                color: '#136AEC',
                fillColor: '#2A93EE',
                fillOpacity: 0.7,
                weight: 2,
                opacity: 0.9,
                radius: 5
            },
            // changes to range circle and inner marker while following
            // it is only necessary to provide the things that should change
            followCircleStyle: {},
            followMarkerStyle: {
                //color: '#FFA500',
                //fillColor: '#FFB000'
            },
            icon: 'fa fa-map-marker',  // fa-location-arrow or fa-map-marker
            iconLoading: 'fa fa-spinner fa-spin',
            circlePadding: [0, 0],
            metric: true,
            onLocationError: function(err) {
                // this event is called in case of any location error
                // that is not a time out error.
                alert(err.message);
            },
            onLocationOutsideMapBounds: function(control) {
                // this event is repeatedly called when the location changes
                control.stopLocate();
                alert(control.options.strings.outsideMapBoundsMsg);
            },
            setView: true, // automatically sets the map view to the user's location
            // keep the current map zoom level when displaying the user's location. (if 'false', use maxZoom)
            keepCurrentZoomLevel: false,
            showPopup: true, // display a popup when the user click on the inner marker
            strings: {
                title: "Show me where I am",
                popup: "You are within {distance} {unit} from this point",
                outsideMapBoundsMsg: "You seem located outside the boundaries of the map"
            },
            locateOptions: {
                maxZoom: Infinity,
                watch: true  // if you overwrite this, visualization cannot be updated
            }
        },

        initialize: function (options) {
            L.Map.addInitHook(function () {
                if (this.options.locateControl) {
                    this.locateControl = L.control.locate();
                    this.addControl(this.locateControl);
                }
            });

            for (var i in options) {
                if (typeof this.options[i] === 'object') {
                    L.extend(this.options[i], options[i]);
                } else {
                    this.options[i] = options[i];
                }
            }
        },

        /**
         * This method launches the location engine.
         * It is called before the marker is updated,
         * event if it does not mean that the event will be ready.
         *
         * Override it if you want to add more functionnalities.
         * It should set the this._active to true and do nothing if
         * this._active is not true.
         */
        start: function(map) {
            if (this.options.setView) {
                this._locateOnNextLocationFound = true;
            }

            if(!this._active) {
                map.locate(this._locateOptions);
            }
            this._active = true;

            if (this.options.follow) {
                this._startFollowing(map);
            }
        },

        /**
         * Called to stop the location engine.
         *
         * Override it to shutdown any functionnalities you added on start.
         */
        stop: function(control) {
            control._map.stopLocate();

            control._map.off('dragstart', this._stopFollowing);
            if (control.options.follow && control._following) {
                this._stopFollowing(control._map);
            }
        },

        /**
         * Draw the resulting marker on the map.
         *
         * Uses the event retrieved from onLocationFound from the map.
         */
        drawMarker: function(map) {
            if (this._event.accuracy === undefined) {
                this._event.accuracy = 0;
            }

            var radius = this._event.accuracy;
            if (this._locateOnNextLocationFound) {
                if (this._isOutsideMapBounds()) {
                    this.options.onLocationOutsideMapBounds(this);
                } else {
                    map.fitBounds(this._event.bounds, {
                        padding: this.options.circlePadding,
                        maxZoom: this.options.keepCurrentZoomLevel ? map.getZoom() : this._locateOptions.maxZoom
                    });
                }
                this._locateOnNextLocationFound = false;
            }

            // circle with the radius of the location's accuracy
            var style, o;
            if (this.options.drawCircle) {
                if (this._following) {
                    style = this.options.followCircleStyle;
                } else {
                    style = this.options.circleStyle;
                }

                if (!this._circle) {
                    this._circle = L.circle(this._event.latlng, radius, style)
                    .addTo(this._layer);
                } else {
                    this._circle.setLatLng(this._event.latlng).setRadius(radius);
                    for (o in style) {
                        this._circle.options[o] = style[o];
                    }
                }
            }

            var distance, unit;
            if (this.options.metric) {
                distance = radius.toFixed(0);
                unit = "meters";
            } else {
                distance = (radius * 3.2808399).toFixed(0);
                unit = "feet";
            }

            // small inner marker
            var mStyle;
            if (this._following) {
                mStyle = this.options.followMarkerStyle;
            } else {
                mStyle = this.options.markerStyle;
            }

            if (!this._marker) {
                this._marker = this.createMarker(this._event.latlng, mStyle)
                .addTo(this._layer);
            } else {
                this.updateMarker(this._event.latlng, mStyle);
            }

            var t = this.options.strings.popup;
            if (this.options.showPopup && t) {
                this._marker.bindPopup(L.Util.template(t, {distance: distance, unit: unit}))
                ._popup.setLatLng(this._event.latlng);
            }

            this._toggleContainerStyle();
        },

        /**
         * Creates the marker.
         *
         * Should return the base marker so it is possible to bind a popup if the
         * option is activated.
         *
         * Used by drawMarker, you can ignore it if you have overriden it.
         */
        createMarker: function(latlng, mStyle) {
            return this.options.markerClass(latlng, mStyle)
        },

        /**
         * Updates the marker with current coordinates.
         *
         * Used by drawMarker, you can ignore it if you have overriden it.
         */
        updateMarker: function(latlng, mStyle) {
            this._marker.setLatLng();
            for (o in mStyle) {
                this._marker.options[o] = mStyle[o];
            }
        },

        /**
         * Remove the marker from map.
         */
        removeMarker: function(control) {
            control._layer.clearLayers();
            control._marker = undefined;
            control._circle = undefined;
        },

        onAdd: function (map) {
            var container = L.DomUtil.create('div',
                'leaflet-control-locate leaflet-bar leaflet-control');

            this._layer = new L.LayerGroup();
            this._layer.addTo(map);
            this._event = undefined;

            this._locateOptions = this.options.locateOptions;
            L.extend(this._locateOptions, this.options.locateOptions);
            L.extend(this._locateOptions, {
                setView: false // have to set this to false because we have to
                               // do setView manually
            });

            // extend the follow marker style and circle from the normal style
            var tmp = {};
            L.extend(tmp, this.options.markerStyle, this.options.followMarkerStyle);
            this.options.followMarkerStyle = tmp;
            tmp = {};
            L.extend(tmp, this.options.circleStyle, this.options.followCircleStyle);
            this.options.followCircleStyle = tmp;

            this._link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
            this._link.href = '#';
            this._link.title = this.options.strings.title;
            this._icon = L.DomUtil.create('span', this.options.icon, this._link);

            L.DomEvent
                .on(this._link, 'click', L.DomEvent.stopPropagation)
                .on(this._link, 'click', L.DomEvent.preventDefault)
                .on(this._link, 'click', function() {
                    var shouldStop = (this._event === undefined || this._map.getBounds().contains(this._event.latlng)
                        || !this.options.setView || this._isOutsideMapBounds());
                    if (!this.options.remainActive && (this._active && shouldStop)) {
                        this._deactivate(this);
                    } else {
                        this._activate(map);
                    }
                }, this)
                .on(this._link, 'dblclick', L.DomEvent.stopPropagation);

            this._resetVariables();
            this.bindEvents(map);

            return container;
        },

        /**
         * Binds the actions to the map events.
         */
        bindEvents: function(map) {
            map.on('locationfound', this._onLocationFound, this, this);
            map.on('locationerror', this._onLocationError, this, this);
            map.on('unload', this._deactivate, this, this);
        }

        /**
         * Activates the plugin:
         * - calls the engine,
         * - draws the marker (if coordinates available)
         */
        _activate: function(map) {
            this.start(map);

            if (!this._event) {
                this._setClasses('requesting');
            } else {
                this.drawMarker(map);
            }
        },

        /**
         * Deactivates the plugin:
         * - stops the engine,
         * - reinitalizes the button,
         * - removes the marker
         */
        _deactivate: function(control) {
            this.stop(control);

            this._cleanClasses();
            this._resetVariables();

            this.removeMarker(control);
        },

        /**
         * Calls deactivate and dispatches an error.
         */
        _onLocationError: function(err) {
            // ignore time out error if the location is watched
            if (err.code == 3 && this._locateOptions.watch) {
                return;
            }

            this._deactivate(this);
            this.options.onLocationError(err);
        },

        /**
         * Stores the received event and updates the marker.
         */
        _onLocationFound: function(e) {
            // no need to do anything if the location has not changed
            if (this._event &&
                (this._event.latlng.lat === e.latlng.lat &&
                 this._event.latlng.lng === e.latlng.lng &&
                     this._event.accuracy === e.accuracy)) {
                return;
            }

            if (!this._active) {
                return;
            }

            this._event = e;

            if (this.options.follow && this._following) {
                this._locateOnNextLocationFound = true;
            }

            this.drawMarker(this._map);
        },

        /**
         * Dispatches the 'startfollowing' event on map.
         */
        _startFollowing: function(map) {
            map.fire('startfollowing', this);
            this._following = true;
            if (this.options.stopFollowingOnDrag) {
                map.on('dragstart', this._stopFollowing);
            }
        },

        /**
         * Dispatches the 'stopfollowing' event on map.
         */
        _stopFollowing: function(map) {
            map.fire('stopfollowing', this);
            this._following = false;
            if (this.options.stopFollowingOnDrag) {
                map.off('dragstart', this._stopFollowing);
            }
            this._toggleContainerStyle();
        },

        /**
         * Check if location is in map bounds
         */
        _isOutsideMapBounds: function() {
            if (this._event === undefined)
                return false;
            return this._map.options.maxBounds &&
                !this._map.options.maxBounds.contains(this._event.latlng);
        },

        /**
         * Toggles button class.
         */
        _toggleContainerStyle: function() {
            if (!this._container) {
                return;
            }

            if (this._following) {
                this._setClasses('following');
            } else {
                this._setClasses('active');
            }
        },

        _setClasses: function(state) {
            if (state == 'requesting') {
                L.DomUtil.removeClasses(this._container, "active following");
                L.DomUtil.addClasses(this._container, "requesting");

                L.DomUtil.removeClasses(this._icon, this.options.icon);
                L.DomUtil.addClasses(this._icon, this.options.iconLoading);
            } else if (state == 'active') {
                L.DomUtil.removeClasses(this._container, "requesting following");
                L.DomUtil.addClasses(this._container, "active");

                L.DomUtil.removeClasses(this._icon, this.options.iconLoading);
                L.DomUtil.addClasses(this._icon, this.options.icon);
            } else if (state == 'following') {
                L.DomUtil.removeClasses(this._container, "requesting");
                L.DomUtil.addClasses(this._container, "active following");

                L.DomUtil.removeClasses(this._icon, this.options.iconLoading);
                L.DomUtil.addClasses(this._icon, this.options.icon);
            }
        },

        /**
         * Removes all classes from button.
         */
        _cleanClasses: function() {
            L.DomUtil.removeClass(this._container, "requesting");
            L.DomUtil.removeClass(this._container, "active");
            L.DomUtil.removeClass(this._container, "following");
        },

        /**
         * Reinitializes attributes.
         */
        _resetVariables: function() {
            this._active = false;
            this._locateOnNextLocationFound = this.options.setView;
            this._following = false;
        }
    });

    L.Map.addInitHook(function () {
        if (this.options.locateControl) {
            this.locateControl = L.control.locate();
            this.addControl(this.locateControl);
        }
    });

    L.control.locate = function (options) {
        return new L.Control.Locate(options);
    };

    (function(){
      // leaflet.js raises bug when trying to addClass / removeClass multiple classes at once
      // Let's create a wrapper on it which fixes it.
      var LDomUtilApplyClassesMethod = function(method, element, classNames) {
        classNames = classNames.split(' ');
        classNames.forEach(function(className) {
            L.DomUtil[method].call(this, element, className);
        });
      };

      L.DomUtil.addClasses = function(el, names) { LDomUtilApplyClassesMethod('addClass', el, names); };
      L.DomUtil.removeClasses = function(el, names) { LDomUtilApplyClassesMethod('removeClass', el, names); };
    })();
    return L.Control.Locate;
}, window));
<commit_msg>Fix typo<commit_after>/*!
Copyright (c) 2014 Dominik Moritz

This file is part of the leaflet locate control. It is licensed under the MIT license.
You can find the project at: https://github.com/domoritz/leaflet-locatecontrol
*/
(function (factory, window) {
     // see https://github.com/Leaflet/Leaflet/blob/master/PLUGIN-GUIDE.md#module-loaders
     // for details on how to structure a leaflet plugin.

    // define an AMD module that relies on 'leaflet'
    if (typeof define === 'function' && define.amd) {
        define(['leaflet'], factory);

    // define a Common JS module that relies on 'leaflet'
    } else if (typeof exports === 'object') {
        module.exports = factory(require('leaflet'));
    }

    // attach your plugin to the global 'L' variable
    if(typeof window !== 'undefined' && window.L){
        window.L.Locate = factory(L);
    }

} (function (L){
    L.Control.Locate = L.Control.extend({
        options: {
            position: 'topleft',
            drawCircle: true,
            follow: false,  // follow with zoom and pan the user's location
            stopFollowingOnDrag: false, // if follow is true, stop following when map is dragged (deprecated)
            // if true locate control remains active on click even if the user's location is in view.
            // clicking control will just pan to location
            remainActive: false,
            markerClass: L.circleMarker, // L.circleMarker or L.marker
            // range circle
            circleStyle: {
                color: '#136AEC',
                fillColor: '#136AEC',
                fillOpacity: 0.15,
                weight: 2,
                opacity: 0.5
            },
            // inner marker
            markerStyle: {
                color: '#136AEC',
                fillColor: '#2A93EE',
                fillOpacity: 0.7,
                weight: 2,
                opacity: 0.9,
                radius: 5
            },
            // changes to range circle and inner marker while following
            // it is only necessary to provide the things that should change
            followCircleStyle: {},
            followMarkerStyle: {
                //color: '#FFA500',
                //fillColor: '#FFB000'
            },
            icon: 'fa fa-map-marker',  // fa-location-arrow or fa-map-marker
            iconLoading: 'fa fa-spinner fa-spin',
            circlePadding: [0, 0],
            metric: true,
            onLocationError: function(err) {
                // this event is called in case of any location error
                // that is not a time out error.
                alert(err.message);
            },
            onLocationOutsideMapBounds: function(control) {
                // this event is repeatedly called when the location changes
                control.stopLocate();
                alert(control.options.strings.outsideMapBoundsMsg);
            },
            setView: true, // automatically sets the map view to the user's location
            // keep the current map zoom level when displaying the user's location. (if 'false', use maxZoom)
            keepCurrentZoomLevel: false,
            showPopup: true, // display a popup when the user click on the inner marker
            strings: {
                title: "Show me where I am",
                popup: "You are within {distance} {unit} from this point",
                outsideMapBoundsMsg: "You seem located outside the boundaries of the map"
            },
            locateOptions: {
                maxZoom: Infinity,
                watch: true  // if you overwrite this, visualization cannot be updated
            }
        },

        initialize: function (options) {
            L.Map.addInitHook(function () {
                if (this.options.locateControl) {
                    this.locateControl = L.control.locate();
                    this.addControl(this.locateControl);
                }
            });

            for (var i in options) {
                if (typeof this.options[i] === 'object') {
                    L.extend(this.options[i], options[i]);
                } else {
                    this.options[i] = options[i];
                }
            }
        },

        /**
         * This method launches the location engine.
         * It is called before the marker is updated,
         * event if it does not mean that the event will be ready.
         *
         * Override it if you want to add more functionnalities.
         * It should set the this._active to true and do nothing if
         * this._active is not true.
         */
        start: function(map) {
            if (this.options.setView) {
                this._locateOnNextLocationFound = true;
            }

            if(!this._active) {
                map.locate(this._locateOptions);
            }
            this._active = true;

            if (this.options.follow) {
                this._startFollowing(map);
            }
        },

        /**
         * Called to stop the location engine.
         *
         * Override it to shutdown any functionnalities you added on start.
         */
        stop: function(control) {
            control._map.stopLocate();

            control._map.off('dragstart', this._stopFollowing);
            if (control.options.follow && control._following) {
                this._stopFollowing(control._map);
            }
        },

        /**
         * Draw the resulting marker on the map.
         *
         * Uses the event retrieved from onLocationFound from the map.
         */
        drawMarker: function(map) {
            if (this._event.accuracy === undefined) {
                this._event.accuracy = 0;
            }

            var radius = this._event.accuracy;
            if (this._locateOnNextLocationFound) {
                if (this._isOutsideMapBounds()) {
                    this.options.onLocationOutsideMapBounds(this);
                } else {
                    map.fitBounds(this._event.bounds, {
                        padding: this.options.circlePadding,
                        maxZoom: this.options.keepCurrentZoomLevel ? map.getZoom() : this._locateOptions.maxZoom
                    });
                }
                this._locateOnNextLocationFound = false;
            }

            // circle with the radius of the location's accuracy
            var style, o;
            if (this.options.drawCircle) {
                if (this._following) {
                    style = this.options.followCircleStyle;
                } else {
                    style = this.options.circleStyle;
                }

                if (!this._circle) {
                    this._circle = L.circle(this._event.latlng, radius, style)
                    .addTo(this._layer);
                } else {
                    this._circle.setLatLng(this._event.latlng).setRadius(radius);
                    for (o in style) {
                        this._circle.options[o] = style[o];
                    }
                }
            }

            var distance, unit;
            if (this.options.metric) {
                distance = radius.toFixed(0);
                unit = "meters";
            } else {
                distance = (radius * 3.2808399).toFixed(0);
                unit = "feet";
            }

            // small inner marker
            var mStyle;
            if (this._following) {
                mStyle = this.options.followMarkerStyle;
            } else {
                mStyle = this.options.markerStyle;
            }

            if (!this._marker) {
                this._marker = this.createMarker(this._event.latlng, mStyle)
                .addTo(this._layer);
            } else {
                this.updateMarker(this._event.latlng, mStyle);
            }

            var t = this.options.strings.popup;
            if (this.options.showPopup && t) {
                this._marker.bindPopup(L.Util.template(t, {distance: distance, unit: unit}))
                ._popup.setLatLng(this._event.latlng);
            }

            this._toggleContainerStyle();
        },

        /**
         * Creates the marker.
         *
         * Should return the base marker so it is possible to bind a popup if the
         * option is activated.
         *
         * Used by drawMarker, you can ignore it if you have overriden it.
         */
        createMarker: function(latlng, mStyle) {
            return this.options.markerClass(latlng, mStyle)
        },

        /**
         * Updates the marker with current coordinates.
         *
         * Used by drawMarker, you can ignore it if you have overriden it.
         */
        updateMarker: function(latlng, mStyle) {
            this._marker.setLatLng();
            for (o in mStyle) {
                this._marker.options[o] = mStyle[o];
            }
        },

        /**
         * Remove the marker from map.
         */
        removeMarker: function(control) {
            control._layer.clearLayers();
            control._marker = undefined;
            control._circle = undefined;
        },

        onAdd: function (map) {
            var container = L.DomUtil.create('div',
                'leaflet-control-locate leaflet-bar leaflet-control');

            this._layer = new L.LayerGroup();
            this._layer.addTo(map);
            this._event = undefined;

            this._locateOptions = this.options.locateOptions;
            L.extend(this._locateOptions, this.options.locateOptions);
            L.extend(this._locateOptions, {
                setView: false // have to set this to false because we have to
                               // do setView manually
            });

            // extend the follow marker style and circle from the normal style
            var tmp = {};
            L.extend(tmp, this.options.markerStyle, this.options.followMarkerStyle);
            this.options.followMarkerStyle = tmp;
            tmp = {};
            L.extend(tmp, this.options.circleStyle, this.options.followCircleStyle);
            this.options.followCircleStyle = tmp;

            this._link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
            this._link.href = '#';
            this._link.title = this.options.strings.title;
            this._icon = L.DomUtil.create('span', this.options.icon, this._link);

            L.DomEvent
                .on(this._link, 'click', L.DomEvent.stopPropagation)
                .on(this._link, 'click', L.DomEvent.preventDefault)
                .on(this._link, 'click', function() {
                    var shouldStop = (this._event === undefined || this._map.getBounds().contains(this._event.latlng)
                        || !this.options.setView || this._isOutsideMapBounds());
                    if (!this.options.remainActive && (this._active && shouldStop)) {
                        this._deactivate(this);
                    } else {
                        this._activate(map);
                    }
                }, this)
                .on(this._link, 'dblclick', L.DomEvent.stopPropagation);

            this._resetVariables();
            this.bindEvents(map);

            return container;
        },

        /**
         * Binds the actions to the map events.
         */
        bindEvents: function(map) {
            map.on('locationfound', this._onLocationFound, this, this);
            map.on('locationerror', this._onLocationError, this, this);
            map.on('unload', this._deactivate, this, this);
        },

        /**
         * Activates the plugin:
         * - calls the engine,
         * - draws the marker (if coordinates available)
         */
        _activate: function(map) {
            this.start(map);

            if (!this._event) {
                this._setClasses('requesting');
            } else {
                this.drawMarker(map);
            }
        },

        /**
         * Deactivates the plugin:
         * - stops the engine,
         * - reinitalizes the button,
         * - removes the marker
         */
        _deactivate: function(control) {
            this.stop(control);

            this._cleanClasses();
            this._resetVariables();

            this.removeMarker(control);
        },

        /**
         * Calls deactivate and dispatches an error.
         */
        _onLocationError: function(err) {
            // ignore time out error if the location is watched
            if (err.code == 3 && this._locateOptions.watch) {
                return;
            }

            this._deactivate(this);
            this.options.onLocationError(err);
        },

        /**
         * Stores the received event and updates the marker.
         */
        _onLocationFound: function(e) {
            // no need to do anything if the location has not changed
            if (this._event &&
                (this._event.latlng.lat === e.latlng.lat &&
                 this._event.latlng.lng === e.latlng.lng &&
                     this._event.accuracy === e.accuracy)) {
                return;
            }

            if (!this._active) {
                return;
            }

            this._event = e;

            if (this.options.follow && this._following) {
                this._locateOnNextLocationFound = true;
            }

            this.drawMarker(this._map);
        },

        /**
         * Dispatches the 'startfollowing' event on map.
         */
        _startFollowing: function(map) {
            map.fire('startfollowing', this);
            this._following = true;
            if (this.options.stopFollowingOnDrag) {
                map.on('dragstart', this._stopFollowing);
            }
        },

        /**
         * Dispatches the 'stopfollowing' event on map.
         */
        _stopFollowing: function(map) {
            map.fire('stopfollowing', this);
            this._following = false;
            if (this.options.stopFollowingOnDrag) {
                map.off('dragstart', this._stopFollowing);
            }
            this._toggleContainerStyle();
        },

        /**
         * Check if location is in map bounds
         */
        _isOutsideMapBounds: function() {
            if (this._event === undefined)
                return false;
            return this._map.options.maxBounds &&
                !this._map.options.maxBounds.contains(this._event.latlng);
        },

        /**
         * Toggles button class.
         */
        _toggleContainerStyle: function() {
            if (!this._container) {
                return;
            }

            if (this._following) {
                this._setClasses('following');
            } else {
                this._setClasses('active');
            }
        },

        _setClasses: function(state) {
            if (state == 'requesting') {
                L.DomUtil.removeClasses(this._container, "active following");
                L.DomUtil.addClasses(this._container, "requesting");

                L.DomUtil.removeClasses(this._icon, this.options.icon);
                L.DomUtil.addClasses(this._icon, this.options.iconLoading);
            } else if (state == 'active') {
                L.DomUtil.removeClasses(this._container, "requesting following");
                L.DomUtil.addClasses(this._container, "active");

                L.DomUtil.removeClasses(this._icon, this.options.iconLoading);
                L.DomUtil.addClasses(this._icon, this.options.icon);
            } else if (state == 'following') {
                L.DomUtil.removeClasses(this._container, "requesting");
                L.DomUtil.addClasses(this._container, "active following");

                L.DomUtil.removeClasses(this._icon, this.options.iconLoading);
                L.DomUtil.addClasses(this._icon, this.options.icon);
            }
        },

        /**
         * Removes all classes from button.
         */
        _cleanClasses: function() {
            L.DomUtil.removeClass(this._container, "requesting");
            L.DomUtil.removeClass(this._container, "active");
            L.DomUtil.removeClass(this._container, "following");
        },

        /**
         * Reinitializes attributes.
         */
        _resetVariables: function() {
            this._active = false;
            this._locateOnNextLocationFound = this.options.setView;
            this._following = false;
        }
    });

    L.Map.addInitHook(function () {
        if (this.options.locateControl) {
            this.locateControl = L.control.locate();
            this.addControl(this.locateControl);
        }
    });

    L.control.locate = function (options) {
        return new L.Control.Locate(options);
    };

    (function(){
      // leaflet.js raises bug when trying to addClass / removeClass multiple classes at once
      // Let's create a wrapper on it which fixes it.
      var LDomUtilApplyClassesMethod = function(method, element, classNames) {
        classNames = classNames.split(' ');
        classNames.forEach(function(className) {
            L.DomUtil[method].call(this, element, className);
        });
      };

      L.DomUtil.addClasses = function(el, names) { LDomUtilApplyClassesMethod('addClass', el, names); };
      L.DomUtil.removeClasses = function(el, names) { LDomUtilApplyClassesMethod('removeClass', el, names); };
    })();
    return L.Control.Locate;
}, window));
<|endoftext|>


<commit_before>(function(scope){

	'use strict';

	ImprintJs.registerTest("screenResolution", function(){
		return new Promise(function(resolve) {
			return resolve(screen.width + "x" + screen.height);
		});
	});

})(window);<commit_msg>Detect orientation<commit_after>(function(scope){

	'use strict';

	ImprintJs.registerTest("screenResolution", function(){
		return new Promise(function(resolve) {
			var val = (screen.height > screen.width)
				? [screen.height, screen.width]
				: [screen.width, screen.height];
			return resolve(val.join("x"));
		});
	});

})(window);
<|endoftext|>


<commit_before>/*
 * mobile
 * Convert data to the API version as expected by mobile app
 */
'use strict';

var fs = require('fs');
var ent = require('ent');
var YAML = require('yamljs');
var shell = require('shelljs');
var deHtml = function(s) {
  if (s) {
    s = s.replace(/
/g, '\n');
    s = s.replace(//g, '');
    s = s.replace(/<\/[a-zA-Z]*>/g, '');
    s = ent.decode(s);
  }
  return s;
};

var src = '_data';
var trg = '_site/api';
// load files from src: speakers.yml, sessions.yml, schedule-data.yml
var speakers = YAML.load(src + '/speakers.yml');
var sessions = YAML.load(src + '/sessions.yml');
var schedule = YAML.load(src + '/schedule.yml');
// give each speaker a unique number
// create output arrays
var i, j, k;
var speakerNum = {};
var speakersOut = [];
var aSpeaker;
for (i=0; i<speakers.length; i++) {
  if (!speakers[i].current) continue;
  speakerNum[speakers[i].id] = i+1;
  aSpeaker = {
    'bio': deHtml(speakers[i].bio),
    'id': i+1,
    'name': speakers[i].name + ' ' + speakers[i].surname,
    'photo': 'http://www.devfest.at/img/speakers/' + speakers[i].thumbnailUrl
  }
  if (speakers[i].title && speakers[i].company) {
    aSpeaker.title = speakers[i].title + ', ' + speakers[i].company;
  }
  else if (speakers[i].title) {
    aSpeaker.title = speakers[i].title;
  }
  else {
    aSpeaker.title = speakers[i].company;
  }
  if (speakers[i].social) {
    for (j=0; j<speakers[i].social.length; j++) {
      var aLink = speakers[i].social[j];
      if (aLink.name == "twitter") {
        aSpeaker.twitter = aLink.link.replace(/https?:\/\/w?w?w?.?twitter.com\//, '');
      }
      else if (aLink.name == "google-plus") {
        aSpeaker.gplus = aLink.link;
      }
      else if (aLink.name == "linkedin") {
        aSpeaker.linkedin = aLink.link;
      }
      else if (aLink.name == "github") {
        aSpeaker.github = aLink.link.replace(/https?:\/\/w?w?w?.?github.com\//, '');
      }
      else if (aLink.link.indexOf("xing.com") !== -1) {
        aSpeaker.xing = aLink.link;
      }
      else {
        aSpeaker.website = aLink.link;
      }
    }
  }
  speakersOut[i] = aSpeaker;
}
// create assoc of sessions by id
var sessionsById = {};
for (i=0; i<sessions.length; i++) {
  sessionsById[sessions[i].id] = sessions[i];
}
var x = 1;
var sessionsOut = [];
// create output sessions
for (i=0; i<schedule.length; i++) {
  for (j=0; j<schedule[i].timeslots.length; j++) {
    for (k=0; k<schedule[i].timeslots[j].sessionIds.length; k++) {
      var sessionId = schedule[i].timeslots[j].sessionIds[k];
      if (sessionId in sessionsById) {
        var aSession = {
          'description': deHtml(sessionsById[sessionId].description),
          'id': x,
          'title': deHtml(sessionsById[sessionId].title)
        };
        x++;
        // get session image (if exists)
        if ('imageUrl' in sessionsById[sessionId]) {
          aSession.photo = 'http://www.devfest.at/img/' + sessionsById[sessionId].imageUrl;
        }
        // get the duration
        var date1 = schedule[i].date + ' ' + schedule[i].timeslots[j].startTime;
        var date2 = schedule[i].date + ' ' + schedule[i].timeslots[j].endTime;
        var duration = ((new Date(date2).getTime()) - (new Date(date1).getTime())) / (1000 * 60);
        aSession.startAt = date1;
        aSession.duration = duration;
        var sessionSpeakers = [];
        if ('speakers' in sessionsById[sessionId]) {
          for (var t=0; t<sessionsById[sessionId].speakers.length; t++) {
            var speakerStrId = sessionsById[sessionId].speakers[t];
            if (speakerStrId in speakerNum) {
              sessionSpeakers.push(speakerNum[speakerStrId]);
            }
          }
        }
        if (sessionSpeakers.length) {
          aSession.speakersId = sessionSpeakers;
        }
        // get the room id
        if (schedule[i].timeslots[j].sessionIds.length == 1) {
          if (sessionsById[sessionId].service) {
            // we have a service session
            aSession.roomId = 0;
          }
          else {
            // we have a content session
            aSession.roomId = 1;
          }
        }
        else if (schedule[i].timeslots[j].sessionIds.length == 2) {
          // first session in room 1, second in room 2
          if (k == 0) {
            aSession.roomId = 1;
          }
          else {
            aSession.roomId = 2;
          }
        }
        else {
          aSession.roomId = k + 1;
        }
        // add session
        sessionsOut.push(aSession);
      }
    }
  }
}
// serialize sessions & speakers to file
try {
  fs.accessSync(trg);
}
catch(e) {
  // fs.mkdirSync(trg);
  shell.mkdir('-p', trg);
}
try {
  fs.accessSync(trg + '/v1');
}
catch(e) {
  fs.mkdirSync(trg + '/v1');
}
fs.writeFileSync(trg + '/v1/speakers', JSON.stringify(speakersOut));
fs.writeFileSync(trg + '/v1/sessions', JSON.stringify(sessionsOut));
<commit_msg>Add .json to API files<commit_after>/*
 * mobile
 * Convert data to the API version as expected by mobile app
 */
'use strict';

var fs = require('fs');
var ent = require('ent');
var YAML = require('yamljs');
var shell = require('shelljs');
var deHtml = function(s) {
  if (s) {
    s = s.replace(/
/g, '\n');
    s = s.replace(//g, '');
    s = s.replace(/<\/[a-zA-Z]*>/g, '');
    s = ent.decode(s);
  }
  return s;
};

var src = '_data';
var trg = '_site/api';
// load files from src: speakers.yml, sessions.yml, schedule-data.yml
var speakers = YAML.load(src + '/speakers.yml');
var sessions = YAML.load(src + '/sessions.yml');
var schedule = YAML.load(src + '/schedule.yml');
// give each speaker a unique number
// create output arrays
var i, j, k;
var speakerNum = {};
var speakersOut = [];
var aSpeaker;
for (i=0; i<speakers.length; i++) {
  if (!speakers[i].current) continue;
  speakerNum[speakers[i].id] = i+1;
  aSpeaker = {
    'bio': deHtml(speakers[i].bio),
    'id': i+1,
    'name': speakers[i].name + ' ' + speakers[i].surname,
    'photo': 'http://www.devfest.at/img/speakers/' + speakers[i].thumbnailUrl
  }
  if (speakers[i].title && speakers[i].company) {
    aSpeaker.title = speakers[i].title + ', ' + speakers[i].company;
  }
  else if (speakers[i].title) {
    aSpeaker.title = speakers[i].title;
  }
  else {
    aSpeaker.title = speakers[i].company;
  }
  if (speakers[i].social) {
    for (j=0; j<speakers[i].social.length; j++) {
      var aLink = speakers[i].social[j];
      if (aLink.name == "twitter") {
        aSpeaker.twitter = aLink.link.replace(/https?:\/\/w?w?w?.?twitter.com\//, '');
      }
      else if (aLink.name == "google-plus") {
        aSpeaker.gplus = aLink.link;
      }
      else if (aLink.name == "linkedin") {
        aSpeaker.linkedin = aLink.link;
      }
      else if (aLink.name == "github") {
        aSpeaker.github = aLink.link.replace(/https?:\/\/w?w?w?.?github.com\//, '');
      }
      else if (aLink.link.indexOf("xing.com") !== -1) {
        aSpeaker.xing = aLink.link;
      }
      else {
        aSpeaker.website = aLink.link;
      }
    }
  }
  speakersOut[i] = aSpeaker;
}
// create assoc of sessions by id
var sessionsById = {};
for (i=0; i<sessions.length; i++) {
  sessionsById[sessions[i].id] = sessions[i];
}
var x = 1;
var sessionsOut = [];
// create output sessions
for (i=0; i<schedule.length; i++) {
  for (j=0; j<schedule[i].timeslots.length; j++) {
    for (k=0; k<schedule[i].timeslots[j].sessionIds.length; k++) {
      var sessionId = schedule[i].timeslots[j].sessionIds[k];
      if (sessionId in sessionsById) {
        var aSession = {
          'description': deHtml(sessionsById[sessionId].description),
          'id': x,
          'title': deHtml(sessionsById[sessionId].title)
        };
        x++;
        // get session image (if exists)
        if ('imageUrl' in sessionsById[sessionId]) {
          aSession.photo = 'http://www.devfest.at/img/' + sessionsById[sessionId].imageUrl;
        }
        // get the duration
        var date1 = schedule[i].date + ' ' + schedule[i].timeslots[j].startTime;
        var date2 = schedule[i].date + ' ' + schedule[i].timeslots[j].endTime;
        var duration = ((new Date(date2).getTime()) - (new Date(date1).getTime())) / (1000 * 60);
        aSession.startAt = date1;
        aSession.duration = duration;
        var sessionSpeakers = [];
        if ('speakers' in sessionsById[sessionId]) {
          for (var t=0; t<sessionsById[sessionId].speakers.length; t++) {
            var speakerStrId = sessionsById[sessionId].speakers[t];
            if (speakerStrId in speakerNum) {
              sessionSpeakers.push(speakerNum[speakerStrId]);
            }
          }
        }
        if (sessionSpeakers.length) {
          aSession.speakersId = sessionSpeakers;
        }
        // get the room id
        if (schedule[i].timeslots[j].sessionIds.length == 1) {
          if (sessionsById[sessionId].service) {
            // we have a service session
            aSession.roomId = 0;
          }
          else {
            // we have a content session
            aSession.roomId = 1;
          }
        }
        else if (schedule[i].timeslots[j].sessionIds.length == 2) {
          // first session in room 1, second in room 2
          if (k == 0) {
            aSession.roomId = 1;
          }
          else {
            aSession.roomId = 2;
          }
        }
        else {
          aSession.roomId = k + 1;
        }
        // add session
        sessionsOut.push(aSession);
      }
    }
  }
}
// serialize sessions & speakers to file
try {
  fs.accessSync(trg);
}
catch(e) {
  // fs.mkdirSync(trg);
  shell.mkdir('-p', trg);
}
try {
  fs.accessSync(trg + '/v1');
}
catch(e) {
  fs.mkdirSync(trg + '/v1');
}
fs.writeFileSync(trg + '/v1/speakers.json', JSON.stringify(speakersOut));
fs.writeFileSync(trg + '/v1/sessions.json', JSON.stringify(sessionsOut));
<|endoftext|>


<commit_before>var Trans = (function(){

	/**
	 * This function returns another function which do the transformation
	 * @param  {lookup table} lookupTable A lookup table to replace the keys with values
	 * @return {function} a function which takes a text and replace the keys in it with the equivalent values.
	 */
	function getTranslaterator(lookupTable) {
	    return function(text) {
	        var result = text;
	        for (var key in lookupTable){
						var keyEscaped = key.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
						result = result.replace(new RegExp(keyEscaped, 'gi'), lookupTable[key]);
	        }
	        return result;
	    }
	}

	/**
	 * Constructor of the class
	 * @param {lookup table} lookupTable table used for translateration
	 * @param {lookup table} invLookupTable table used for untranslateration; if it doesn't exist
	 * the first one will be inversed and used for this operation.
	 */
	function Trans(lookupTable, invLookupTable) {
		rlookup = {};
		var transPreFunc;
		var utransPreFunc;
		var transPostFunc;
		var utransPostFunc;
		if (typeof(invLookupTable) !== "undefined"){
			rlookup = invLookupTable;
		} else {
			Object.keys(lookupTable).forEach(function(key) {
				var val = lookupTable[key];
				rlookup[val] = key;
			});
		}

		var translaterator = getTranslaterator(lookupTable);
		var untranslaterator = getTranslaterator(rlookup);

		Trans.prototype.inverseLookup = rlookup;

		Trans.prototype.addTransPreFunction = function (func) {
			if (typeof func === "function"){
				transPreFunc = func;
			}
		}

		Trans.prototype.addUnTransPreFunction = function (func) {
			if (typeof func === "function"){
				utransPreFunc = func;
			}
		}

		Trans.prototype.addTransPostFunction = function (func) {
			if (typeof func === "function"){
				transPostFunc = func;
			}
		}

		Trans.prototype.addUnTransPostFunction = function (func) {
			if (typeof func === "function"){
				utransPostFunc = func;
			}
		}

		Trans.prototype.translaterate = function(text){
			var result = text;

			if (typeof transPreFunc === "function"){
				result = transPreFunc(result);
			}

			result = translaterator(result);

			if (typeof transPostFunc === "function"){
				result = transPostFunc(result);
			}
			return result;
		}

		Trans.prototype.untranslaterate = function(text){
			var result = text;

			if (typeof utransPreFunc === "function"){
				result = utransPreFunc(result);
			}

			result = untranslaterator(result);

			if (typeof utransPostFunc === "function"){
				result = utransPostFunc(result);
			}
			return result;
		}

	}

	return Trans;
}());
<commit_msg>maj and min are different in translateration<commit_after>var Trans = (function(){

	/**
	 * This function returns another function which do the transformation
	 * @param  {lookup table} lookupTable A lookup table to replace the keys with values
	 * @return {function} a function which takes a text and replace the keys in it with the equivalent values.
	 */
	function getTranslaterator(lookupTable) {
	    return function(text) {
	        var result = text;
	        for (var key in lookupTable){
						var keyEscaped = key.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
						result = result.replace(new RegExp(keyEscaped, 'g'), lookupTable[key]);
	        }
	        return result;
	    }
	}

	/**
	 * Constructor of the class
	 * @param {lookup table} lookupTable table used for translateration
	 * @param {lookup table} invLookupTable table used for untranslateration; if it doesn't exist
	 * the first one will be inversed and used for this operation.
	 */
	function Trans(lookupTable, invLookupTable) {
		rlookup = {};
		var transPreFunc;
		var utransPreFunc;
		var transPostFunc;
		var utransPostFunc;
		if (typeof(invLookupTable) !== "undefined"){
			rlookup = invLookupTable;
		} else {
			Object.keys(lookupTable).forEach(function(key) {
				var val = lookupTable[key];
				rlookup[val] = key;
			});
		}

		var translaterator = getTranslaterator(lookupTable);
		var untranslaterator = getTranslaterator(rlookup);

		Trans.prototype.inverseLookup = rlookup;

		Trans.prototype.addTransPreFunction = function (func) {
			if (typeof func === "function"){
				transPreFunc = func;
			}
		}

		Trans.prototype.addUnTransPreFunction = function (func) {
			if (typeof func === "function"){
				utransPreFunc = func;
			}
		}

		Trans.prototype.addTransPostFunction = function (func) {
			if (typeof func === "function"){
				transPostFunc = func;
			}
		}

		Trans.prototype.addUnTransPostFunction = function (func) {
			if (typeof func === "function"){
				utransPostFunc = func;
			}
		}

		Trans.prototype.translaterate = function(text){
			var result = text;

			if (typeof transPreFunc === "function"){
				result = transPreFunc(result);
			}

			result = translaterator(result);

			if (typeof transPostFunc === "function"){
				result = transPostFunc(result);
			}
			return result;
		}

		Trans.prototype.untranslaterate = function(text){
			var result = text;

			if (typeof utransPreFunc === "function"){
				result = utransPreFunc(result);
			}

			result = untranslaterator(result);

			if (typeof utransPostFunc === "function"){
				result = utransPostFunc(result);
			}
			return result;
		}

	}

	return Trans;
}());
<|endoftext|>


<commit_before>import {findNode} from '../lib/utils';
import bodec from 'bodec';

export default function readFileSync(fullPath, encoding) {
  let node = findNode(this.rootNode, fullPath);
  if (!node) throw new Error(`Path does not exist ${fullPath}`);
  if (node.data.isDirectory) throw new Error(`Cannot readFile on a directory ${fullPath}`);

  let contents = bodec.fromRaw(node.data.contents);
  return encoding ? contents.toString(encoding) : contents;
}
<commit_msg>Encoding bug fix<commit_after>import {findNode} from '../lib/utils';
import bodec from 'bodec';

export default function readFileSync(fullPath, encoding) {
  let node = findNode(this.rootNode, fullPath);
  if (!node) throw new Error(`Path does not exist ${fullPath}`);
  if (node.data.isDirectory) throw new Error(`Cannot readFile on a directory ${fullPath}`);

  let contents = bodec.fromRaw(node.data.contents);
  return encoding ? bodec.toString(contents, encoding) : contents;
}
<|endoftext|>


<commit_before>const Cookies            = require('js-cookie');
const moment             = require('moment');
const LocalStore         = require('./storage').LocalStore;
const State              = require('./storage').State;
const defaultRedirectUrl = require('./url').defaultRedirectUrl;
const getPropertyValue   = require('./utility').getPropertyValue;
const isEmptyObject      = require('./utility').isEmptyObject;
const jpClient           = require('../common_functions/country_base').jpClient;
const BinarySocket       = require('../websocket_pages/socket');
const RealityCheckData   = require('../websocket_pages/user/reality_check/reality_check.data');

const Client = (() => {
    'use strict';

    const storage_key = 'client.accounts';
    let client_object = {},
        current_loginid;

    const init = () => {
        current_loginid = LocalStore.get('active_loginid');
        backwardCompatibility();
        client_object = getAllAccountsObject();
    };

    const isLoggedIn = () => (
        !isEmptyObject(getAllAccountsObject()) &&
        get('loginid') &&
        get('token')
    );

    const validateLoginid = () => {
        if (!isLoggedIn()) return;
        const valid_login_ids = new RegExp('^(MX|MF|VRTC|MLT|CR|FOG|VRTJ|JP)[0-9]+$', 'i');
        getAllLoginids().some((loginid) => {
            if (!valid_login_ids.test(loginid)) {
                sendLogoutRequest();
                return true;
            }
            return false;
        });
    };

    /**
     * Stores the client information in local variable and localStorage
     *
     * @param {String} key                 The property name to set
     * @param {String|Number|Object} value The regarding value
     * @param {String|null} loginid        The account to set the value for
     */
    const set = (key, value, loginid = current_loginid) => {
        if (key === 'loginid' && value !== current_loginid) {
            LocalStore.set('active_loginid', value);
            current_loginid = value;
        } else {
            if (!(loginid in client_object)) {
                client_object[loginid] = {};
            }
            client_object[loginid][key] = value;
            LocalStore.setObject(storage_key, client_object);
        }
    };

    /**
     * Returns the client information
     *
     * @param {String|null} key     The property name to return the value from, if missing returns the account object
     * @param {String|null} loginid The account to return the value from
     */
    const get = (key, loginid = current_loginid) => {
        let value;
        if (key === 'loginid') {
            value = loginid || LocalStore.get('active_loginid');
        } else {
            const current_client = client_object[loginid] || getAllAccountsObject()[loginid] || {};
            value = key ? current_client[key] : current_client;
        }
        if (!Array.isArray(value) && (+value === 1 || +value === 0 || value === 'true' || value === 'false')) {
            value = JSON.parse(value || false);
        }
        return value;
    };

    const getAllAccountsObject = () => LocalStore.getObject(storage_key);

    const getAllLoginids = () => Object.keys(getAllAccountsObject());

    const getAccountType = (loginid = current_loginid) => {
        let account_type;
        if (/^VR/.test(loginid))        account_type = 'virtual';
        else if (/^MF/.test(loginid))   account_type = 'financial';
        else if (/^MLT/.test(loginid))  account_type = 'gaming';
        return account_type;
    };

    const isAccountOfType = (type, loginid = current_loginid) => {
        const this_type = getAccountType(loginid);
        return (
            (type === 'virtual' && this_type === 'virtual') ||
            (type === 'real'    && this_type !== 'virtual') ||
            type === this_type);
    };

    const hasAccount = (type, loginid, only_enabled) => (
        isAccountOfType(type, loginid) &&
        (only_enabled ? !get('is_disabled', loginid) : true)
    );

    const getAccountOfType = (type, only_enabled) => {
        const id = getAllLoginids().find(loginid => hasAccount(type, loginid, only_enabled));
        return id ? $.extend({ loginid: id }, get(null, id)) : {};
    };

    const hasAccountType = (type, only_enabled) => !isEmptyObject(getAccountOfType(type, only_enabled));

    const types_map = {
        virtual  : 'Virtual',
        gaming   : 'Gaming',
        financial: 'Investment',
    };
    const getAccountTitle = loginid => types_map[getAccountType(loginid)] || 'Real';

    const hasMultiAccountsOfType = (type, only_enabled) => {
        let number_of_accounts = 0;
        return Object.keys(client_object).some((loginid) => {
            if (hasAccount(type, loginid, only_enabled)) {
                number_of_accounts += 1;
            }
            // as long as has more than one account of type, return true
            return number_of_accounts > 1;
        });
    };

    const responseAuthorize = (response) => {
        const authorize = response.authorize;
        set('email',         authorize.email);
        set('currency',      authorize.currency);
        set('is_virtual',    +authorize.is_virtual);
        set('session_start', parseInt(moment().valueOf() / 1000));
        set('landing_company_shortcode', authorize.landing_company_name);
    };

    const shouldAcceptTnc = () => {
        if (get('is_virtual')) return false;
        const website_tnc_version = State.getResponse('website_status.terms_conditions_version');
        const get_settings = State.getResponse('get_settings');
        return get_settings.hasOwnProperty('client_tnc_status') && get_settings.client_tnc_status !== website_tnc_version;
    };

    const clearAllAccounts = () => {
        current_loginid = undefined;
        client_object = {};
        LocalStore.setObject(storage_key, client_object);

        const hash = window.location.hash;
        if (/no-reality-check/.test(hash)) {
            window.location.hash = hash.replace('no-reality-check', '');
        }
    };

    /**
     * Upgrade the structure of client info to the new one
     * (for clients which already are logged-in with the old version)
     */
    const backwardCompatibility = () => {
        if (!current_loginid) return;

        const accounts_obj    = LocalStore.getObject('client.tokens');
        const current_account = getPropertyValue(accounts_obj, current_loginid) || {};

        // 1. client.tokens = { loginid1: token1, loginid2, token2 }
        if (typeof current_account !== 'object') {
            Object.keys(accounts_obj).forEach((loginid) => {
                accounts_obj[loginid] = { token: current_account };
            });
        }

        // 2. client.tokens = { loginid1: { token: token1, currency: currency1 }, loginid2: { ... } }
        if (!isEmptyObject(accounts_obj)) {
            const keys = ['balance', 'currency', 'email', 'is_virtual', 'residence', 'session_start'];
            // read current client.* values and set in new object
            const setValue = (old_key, new_key) => {
                const value = LocalStore.get(`client.${old_key}`);
                if (value) {
                    accounts_obj[current_loginid][new_key || old_key] = value;
                }
            };
            keys.forEach((key) => { setValue(key); });
            setValue('landing_company_name', 'landing_company_shortcode');

            // remove all client.* and cookies
            Object.keys(LocalStore.storage).forEach((key) => {
                if (/^client\./.test(key)) {
                    LocalStore.remove(key);
                }
            });
            cleanupCookies('email', 'login', 'loginid', 'loginid_list', 'residence');

            // set client.accounts
            LocalStore.setObject(storage_key, accounts_obj);
        }
    };

    const processNewAccount = (options) => {
        if (!options.email || !options.loginid || !options.token) {
            return;
        }

        localStorage.setItem('GTM_new_account', '1');

        set('token',      options.token,       options.loginid);
        set('email',      options.email,       options.loginid);
        set('is_virtual', +options.is_virtual, options.loginid);
        set('loginid',    options.loginid);

        // need to redirect not using pjax
        window.location.href = options.redirect_url || defaultRedirectUrl();
    };

    const hasShortCode = (data, code) => ((data || {}).shortcode === code);

    const canUpgradeGamingToFinancial = data => (hasShortCode(data.financial_company, 'maltainvest'));

    const canUpgradeVirtualToFinancial = data => (!data.gaming_company && hasShortCode(data.financial_company, 'maltainvest'));

    const canUpgradeVirtualToJapan = data => (!data.gaming_company && hasShortCode(data.financial_company, 'japan'));

    const activateByClientType = (section = 'body') => {
        if (isLoggedIn()) {
            BinarySocket.wait('authorize', 'website_status').then(() => {
                $('#client-logged-in').addClass('gr-centered');
                $('.client_logged_in').setVisibility(1);
                if (get('is_virtual')) {
                    $(section).find('.client_virtual').setVisibility(1);
                    $('#topbar').addClass('secondary-bg-color').removeClass('primary-bg-color-dark');
                } else {
                    $(section).find('.client_real').not((jpClient() ? '.ja-hide' : '')).setVisibility(1);
                    $('#topbar').addClass('primary-bg-color-dark').removeClass('secondary-bg-color');
                }
            });
        } else {
            $(section).find('.client_logged_out').setVisibility(1);
            $('#topbar').addClass('primary-bg-color-dark').removeClass('secondary-bg-color');
        }
    };

    const sendLogoutRequest = (show_login_page) => {
        if (show_login_page) {
            sessionStorage.setItem('showLoginPage', 1);
        }
        BinarySocket.send({ logout: '1' });
    };

    const doLogout = (response) => {
        if (response.logout !== 1) return;
        cleanupCookies('login', 'loginid', 'loginid_list', 'email', 'residence', 'settings'); // backward compatibility
        cleanupCookies('reality_check', 'affiliate_token', 'affiliate_tracking');
        clearAllAccounts();
        set('loginid', '');
        RealityCheckData.clear();
        window.location.reload();
    };

    const cleanupCookies = (...cookie_names) => {
        const domains = [
            `.${document.domain.split('.').slice(-2).join('.')}`,
            `.${document.domain}`,
        ];

        let parent_path = window.location.pathname.split('/', 2)[1];
        if (parent_path !== '') {
            parent_path = `/${parent_path}`;
        }

        cookie_names.forEach((c) => {
            Cookies.remove(c, { path: '/', domain: domains[0] });
            Cookies.remove(c, { path: '/', domain: domains[1] });
            Cookies.remove(c);
            if (new RegExp(c).test(document.cookie) && parent_path) {
                Cookies.remove(c, { path: parent_path, domain: domains[0] });
                Cookies.remove(c, { path: parent_path, domain: domains[1] });
                Cookies.remove(c, { path: parent_path });
            }
        });
    };

    const currentLandingCompany = () => {
        const landing_company_response = State.getResponse('landing_company') || {};
        const lc_prop = Object.keys(landing_company_response)
            .find(key => get('landing_company_shortcode') === landing_company_response[key].shortcode);
        return landing_company_response[lc_prop] || {};
    };

    const shouldCompleteTax = () => isAccountOfType('financial') && !/crs_tin_information/.test((State.getResponse('get_account_status') || {}).status);

    const getMT5AccountType = group => (group ? group.replace('\\', '_') : '');

    const getUpgradeInfo = (landing_company, jp_account_status = State.getResponse('get_settings.jp_account_status.status')) => {
        let type = 'real';
        let upgrade_link = 'realws';
        let can_upgrade = false;
        if (get('is_virtual')) {
            if (canUpgradeVirtualToFinancial(landing_company)) {
                type = 'financial';
                upgrade_link = 'maltainvestws';
            } else if (canUpgradeVirtualToJapan(landing_company)) {
                upgrade_link = 'japanws';
            }
            can_upgrade = !hasAccountType('real') && (!jp_account_status || !/jp_knowledge_test_(pending|fail)|jp_activation_pending|activated/.test(jp_account_status));
        } else if (canUpgradeGamingToFinancial(landing_company)) {
            type = 'financial';
            upgrade_link = 'maltainvestws';
            can_upgrade = !hasAccountType('financial');
        }
        return {
            type           : type,
            upgrade_link   : `new_account/${upgrade_link}`,
            can_upgrade    : can_upgrade,
            is_current_path: new RegExp(upgrade_link, 'i').test(window.location.pathname),
        };
    };

    const getLandingCompanyValue = (loginid, landing_company, key) => {
        let landing_company_object;
        if (loginid.financial || isAccountOfType('financial', loginid)) {
            landing_company_object = getPropertyValue(landing_company, 'financial_company');
        } else if (loginid.real || isAccountOfType('real', loginid)) {
            landing_company_object = getPropertyValue(landing_company, 'gaming_company');

            // handle accounts such as japan that don't have gaming company
            if (!landing_company_object) {
                landing_company_object = getPropertyValue(landing_company, 'financial_company');
            }
        } else {
            const financial_company = (getPropertyValue(landing_company, 'financial_company') || {})[key] || [];
            const gaming_company = (getPropertyValue(landing_company, 'gaming_company') || {})[key] || [];
            landing_company_object = financial_company.concat(gaming_company);
            return landing_company_object;
        }
        return (landing_company_object || {})[key];
    };

    return {
        init             : init,
        validateLoginid  : validateLoginid,
        set              : set,
        get              : get,
        getAllLoginids   : getAllLoginids,
        getAccountType   : getAccountType,
        getAccountOfType : getAccountOfType,
        isAccountOfType  : isAccountOfType,
        hasAccountType   : hasAccountType,
        responseAuthorize: responseAuthorize,
        shouldAcceptTnc  : shouldAcceptTnc,
        clearAllAccounts : clearAllAccounts,
        processNewAccount: processNewAccount,
        isLoggedIn       : isLoggedIn,
        sendLogoutRequest: sendLogoutRequest,
        cleanupCookies   : cleanupCookies,
        doLogout         : doLogout,
        shouldCompleteTax: shouldCompleteTax,
        getMT5AccountType: getMT5AccountType,
        getUpgradeInfo   : getUpgradeInfo,
        getAccountTitle  : getAccountTitle,

        hasMultiAccountsOfType: hasMultiAccountsOfType,
        activateByClientType  : activateByClientType,
        currentLandingCompany : currentLandingCompany,
        getLandingCompanyValue: getLandingCompanyValue,
    };
})();

module.exports = Client;
<commit_msg>refactor client functions<commit_after>const Cookies            = require('js-cookie');
const moment             = require('moment');
const LocalStore         = require('./storage').LocalStore;
const State              = require('./storage').State;
const defaultRedirectUrl = require('./url').defaultRedirectUrl;
const getPropertyValue   = require('./utility').getPropertyValue;
const isEmptyObject      = require('./utility').isEmptyObject;
const jpClient           = require('../common_functions/country_base').jpClient;
const BinarySocket       = require('../websocket_pages/socket');
const RealityCheckData   = require('../websocket_pages/user/reality_check/reality_check.data');

const Client = (() => {
    'use strict';

    const storage_key = 'client.accounts';
    let client_object = {},
        current_loginid;

    const init = () => {
        current_loginid = LocalStore.get('active_loginid');
        backwardCompatibility();
        client_object = getAllAccountsObject();
    };

    const isLoggedIn = () => (
        !isEmptyObject(getAllAccountsObject()) &&
        get('loginid') &&
        get('token')
    );

    const validateLoginid = () => {
        if (!isLoggedIn()) return;
        const valid_login_ids = new RegExp('^(MX|MF|VRTC|MLT|CR|FOG|VRTJ|JP)[0-9]+$', 'i');
        getAllLoginids().some((loginid) => {
            if (!valid_login_ids.test(loginid)) {
                sendLogoutRequest();
                return true;
            }
            return false;
        });
    };

    /**
     * Stores the client information in local variable and localStorage
     *
     * @param {String} key                 The property name to set
     * @param {String|Number|Object} value The regarding value
     * @param {String|null} loginid        The account to set the value for
     */
    const set = (key, value, loginid = current_loginid) => {
        if (key === 'loginid' && value !== current_loginid) {
            LocalStore.set('active_loginid', value);
            current_loginid = value;
        } else {
            if (!(loginid in client_object)) {
                client_object[loginid] = {};
            }
            client_object[loginid][key] = value;
            LocalStore.setObject(storage_key, client_object);
        }
    };

    /**
     * Returns the client information
     *
     * @param {String|null} key     The property name to return the value from, if missing returns the account object
     * @param {String|null} loginid The account to return the value from
     */
    const get = (key, loginid = current_loginid) => {
        let value;
        if (key === 'loginid') {
            value = loginid || LocalStore.get('active_loginid');
        } else {
            const current_client = client_object[loginid] || getAllAccountsObject()[loginid] || {};
            value = key ? current_client[key] : current_client;
        }
        if (!Array.isArray(value) && (+value === 1 || +value === 0 || value === 'true' || value === 'false')) {
            value = JSON.parse(value || false);
        }
        return value;
    };

    const getAllAccountsObject = () => LocalStore.getObject(storage_key);

    const getAllLoginids = () => Object.keys(getAllAccountsObject());

    const getAccountType = (loginid = current_loginid) => {
        let account_type;
        if (/^VR/.test(loginid))        account_type = 'virtual';
        else if (/^MF/.test(loginid))   account_type = 'financial';
        else if (/^MLT/.test(loginid))  account_type = 'gaming';
        return account_type;
    };

    const isAccountOfType = (type, loginid = current_loginid, only_enabled = false) => {
        const this_type = getAccountType(loginid);
        return ((
            (type === 'virtual' && this_type === 'virtual') ||
            (type === 'real'    && this_type !== 'virtual') ||
            type === this_type) &&
            only_enabled ? !get('is_disabled', loginid) : true);
    };

    const getAccountOfType = (type, only_enabled) => {
        const id = getAllLoginids().find(loginid => isAccountOfType(type, loginid, only_enabled));
        return id ? $.extend({ loginid: id }, get(null, id)) : {};
    };

    const hasAccountType = (type, only_enabled) => !isEmptyObject(getAccountOfType(type, only_enabled));

    const types_map = {
        virtual  : 'Virtual',
        gaming   : 'Gaming',
        financial: 'Investment',
    };
    const getAccountTitle = loginid => types_map[getAccountType(loginid)] || 'Real';

    const hasMultiAccountsOfType = (type, only_enabled) => {
        let number_of_accounts = 0;
        return getAllLoginids().some((loginid) => {
            number_of_accounts += isAccountOfType(type, loginid, only_enabled);
            // as long as has more than one account of type, return true
            return number_of_accounts > 1;
        });
    };

    const responseAuthorize = (response) => {
        const authorize = response.authorize;
        set('email',         authorize.email);
        set('currency',      authorize.currency);
        set('is_virtual',    +authorize.is_virtual);
        set('session_start', parseInt(moment().valueOf() / 1000));
        set('landing_company_shortcode', authorize.landing_company_name);
    };

    const shouldAcceptTnc = () => {
        if (get('is_virtual')) return false;
        const website_tnc_version = State.getResponse('website_status.terms_conditions_version');
        const get_settings = State.getResponse('get_settings');
        return get_settings.hasOwnProperty('client_tnc_status') && get_settings.client_tnc_status !== website_tnc_version;
    };

    const clearAllAccounts = () => {
        current_loginid = undefined;
        client_object = {};
        LocalStore.setObject(storage_key, client_object);

        const hash = window.location.hash;
        if (/no-reality-check/.test(hash)) {
            window.location.hash = hash.replace('no-reality-check', '');
        }
    };

    /**
     * Upgrade the structure of client info to the new one
     * (for clients which already are logged-in with the old version)
     */
    const backwardCompatibility = () => {
        if (!current_loginid) return;

        const accounts_obj    = LocalStore.getObject('client.tokens');
        const current_account = getPropertyValue(accounts_obj, current_loginid) || {};

        // 1. client.tokens = { loginid1: token1, loginid2, token2 }
        if (typeof current_account !== 'object') {
            Object.keys(accounts_obj).forEach((loginid) => {
                accounts_obj[loginid] = { token: current_account };
            });
        }

        // 2. client.tokens = { loginid1: { token: token1, currency: currency1 }, loginid2: { ... } }
        if (!isEmptyObject(accounts_obj)) {
            const keys = ['balance', 'currency', 'email', 'is_virtual', 'residence', 'session_start'];
            // read current client.* values and set in new object
            const setValue = (old_key, new_key) => {
                const value = LocalStore.get(`client.${old_key}`);
                if (value) {
                    accounts_obj[current_loginid][new_key || old_key] = value;
                }
            };
            keys.forEach((key) => { setValue(key); });
            setValue('landing_company_name', 'landing_company_shortcode');

            // remove all client.* and cookies
            Object.keys(LocalStore.storage).forEach((key) => {
                if (/^client\./.test(key)) {
                    LocalStore.remove(key);
                }
            });
            cleanupCookies('email', 'login', 'loginid', 'loginid_list', 'residence');

            // set client.accounts
            LocalStore.setObject(storage_key, accounts_obj);
        }
    };

    const processNewAccount = (options) => {
        if (!options.email || !options.loginid || !options.token) {
            return;
        }

        localStorage.setItem('GTM_new_account', '1');

        set('token',      options.token,       options.loginid);
        set('email',      options.email,       options.loginid);
        set('is_virtual', +options.is_virtual, options.loginid);
        set('loginid',    options.loginid);

        // need to redirect not using pjax
        window.location.href = options.redirect_url || defaultRedirectUrl();
    };

    const hasShortCode = (data, code) => ((data || {}).shortcode === code);

    const canUpgradeGamingToFinancial = data => (hasShortCode(data.financial_company, 'maltainvest'));

    const canUpgradeVirtualToFinancial = data => (!data.gaming_company && hasShortCode(data.financial_company, 'maltainvest'));

    const canUpgradeVirtualToJapan = data => (!data.gaming_company && hasShortCode(data.financial_company, 'japan'));

    const activateByClientType = (section = 'body') => {
        if (isLoggedIn()) {
            BinarySocket.wait('authorize', 'website_status').then(() => {
                $('#client-logged-in').addClass('gr-centered');
                $('.client_logged_in').setVisibility(1);
                if (get('is_virtual')) {
                    $(section).find('.client_virtual').setVisibility(1);
                    $('#topbar').addClass('secondary-bg-color').removeClass('primary-bg-color-dark');
                } else {
                    $(section).find('.client_real').not((jpClient() ? '.ja-hide' : '')).setVisibility(1);
                    $('#topbar').addClass('primary-bg-color-dark').removeClass('secondary-bg-color');
                }
            });
        } else {
            $(section).find('.client_logged_out').setVisibility(1);
            $('#topbar').addClass('primary-bg-color-dark').removeClass('secondary-bg-color');
        }
    };

    const sendLogoutRequest = (show_login_page) => {
        if (show_login_page) {
            sessionStorage.setItem('showLoginPage', 1);
        }
        BinarySocket.send({ logout: '1' });
    };

    const doLogout = (response) => {
        if (response.logout !== 1) return;
        cleanupCookies('login', 'loginid', 'loginid_list', 'email', 'residence', 'settings'); // backward compatibility
        cleanupCookies('reality_check', 'affiliate_token', 'affiliate_tracking');
        clearAllAccounts();
        set('loginid', '');
        RealityCheckData.clear();
        window.location.reload();
    };

    const cleanupCookies = (...cookie_names) => {
        const domains = [
            `.${document.domain.split('.').slice(-2).join('.')}`,
            `.${document.domain}`,
        ];

        let parent_path = window.location.pathname.split('/', 2)[1];
        if (parent_path !== '') {
            parent_path = `/${parent_path}`;
        }

        cookie_names.forEach((c) => {
            Cookies.remove(c, { path: '/', domain: domains[0] });
            Cookies.remove(c, { path: '/', domain: domains[1] });
            Cookies.remove(c);
            if (new RegExp(c).test(document.cookie) && parent_path) {
                Cookies.remove(c, { path: parent_path, domain: domains[0] });
                Cookies.remove(c, { path: parent_path, domain: domains[1] });
                Cookies.remove(c, { path: parent_path });
            }
        });
    };

    const currentLandingCompany = () => {
        const landing_company_response = State.getResponse('landing_company') || {};
        const lc_prop = Object.keys(landing_company_response)
            .find(key => get('landing_company_shortcode') === landing_company_response[key].shortcode);
        return landing_company_response[lc_prop] || {};
    };

    const shouldCompleteTax = () => isAccountOfType('financial') && !/crs_tin_information/.test((State.getResponse('get_account_status') || {}).status);

    const getMT5AccountType = group => (group ? group.replace('\\', '_') : '');

    const getUpgradeInfo = (landing_company, jp_account_status = State.getResponse('get_settings.jp_account_status.status')) => {
        let type = 'real';
        let upgrade_link = 'realws';
        let can_upgrade = false;
        if (get('is_virtual')) {
            if (canUpgradeVirtualToFinancial(landing_company)) {
                type = 'financial';
                upgrade_link = 'maltainvestws';
            } else if (canUpgradeVirtualToJapan(landing_company)) {
                upgrade_link = 'japanws';
            }
            can_upgrade = !hasAccountType('real') && (!jp_account_status || !/jp_knowledge_test_(pending|fail)|jp_activation_pending|activated/.test(jp_account_status));
        } else if (canUpgradeGamingToFinancial(landing_company)) {
            type = 'financial';
            upgrade_link = 'maltainvestws';
            can_upgrade = !hasAccountType('financial');
        }
        return {
            type           : type,
            upgrade_link   : `new_account/${upgrade_link}`,
            can_upgrade    : can_upgrade,
            is_current_path: new RegExp(upgrade_link, 'i').test(window.location.pathname),
        };
    };

    const getLandingCompanyValue = (loginid, landing_company, key) => {
        let landing_company_object;
        if (loginid.financial || isAccountOfType('financial', loginid)) {
            landing_company_object = getPropertyValue(landing_company, 'financial_company');
        } else if (loginid.real || isAccountOfType('real', loginid)) {
            landing_company_object = getPropertyValue(landing_company, 'gaming_company');

            // handle accounts such as japan that don't have gaming company
            if (!landing_company_object) {
                landing_company_object = getPropertyValue(landing_company, 'financial_company');
            }
        } else {
            const financial_company = (getPropertyValue(landing_company, 'financial_company') || {})[key] || [];
            const gaming_company = (getPropertyValue(landing_company, 'gaming_company') || {})[key] || [];
            landing_company_object = financial_company.concat(gaming_company);
            return landing_company_object;
        }
        return (landing_company_object || {})[key];
    };

    return {
        init             : init,
        validateLoginid  : validateLoginid,
        set              : set,
        get              : get,
        getAllLoginids   : getAllLoginids,
        getAccountType   : getAccountType,
        getAccountOfType : getAccountOfType,
        isAccountOfType  : isAccountOfType,
        hasAccountType   : hasAccountType,
        responseAuthorize: responseAuthorize,
        shouldAcceptTnc  : shouldAcceptTnc,
        clearAllAccounts : clearAllAccounts,
        processNewAccount: processNewAccount,
        isLoggedIn       : isLoggedIn,
        sendLogoutRequest: sendLogoutRequest,
        cleanupCookies   : cleanupCookies,
        doLogout         : doLogout,
        shouldCompleteTax: shouldCompleteTax,
        getMT5AccountType: getMT5AccountType,
        getUpgradeInfo   : getUpgradeInfo,
        getAccountTitle  : getAccountTitle,

        hasMultiAccountsOfType: hasMultiAccountsOfType,
        activateByClientType  : activateByClientType,
        currentLandingCompany : currentLandingCompany,
        getLandingCompanyValue: getLandingCompanyValue,
    };
})();

module.exports = Client;
<|endoftext|>


<commit_before>var State = require('ampersand-state');

var Peers = require('./peers'),
    Peer = require('./peer');

var Channel = function (params) {
  this.name = params.name;
  if (!this.name) {
    throw new Error('name is required');
  }

  this.peers = new Peers();
}

Channel.prototype.addSocket = function (s) {
  var p = new Peer(s, this);
  this.peers.forEach(connectPeer(p));
  this.peers.push(p);
  return p;
}

function connectPeer(sourcePeer) {
  return function (targetPeer) {
    var payload = JSON.stringify({
        action:  'connect',
        source:  sourcePeer.id,
        target:  targetPeer.id,
        payload: /* payload */ '',
      });
    targetPeer.send(payload);
  }
}

/*
function connect(peer) {
  console.log('\n\npeer: ');
  console.log(typeof peer);
  peer.send({
    action: 'connect'
  });
}

var instanceMethods = {
  addPeer: function (p) {
    console.log('addPeer');
    console.log(this.peers.length);

    this.peers.models.forEach(connect);
    this.peers.add(p);
  }
}

var Channel = State.extend(instanceMethods, {
  idAttribute: 'name',
  props: {
    name: {
      type: 'string',
      required: true,
      setOnce: true
    }
  },
  collections: {
    peers: Peers
  }
});
*/

module.exports = Channel;<commit_msg>Remove old implementation<commit_after>var State = require('ampersand-state');

var Peers = require('./peers'),
    Peer = require('./peer');

var Channel = function (params) {
  this.name = params.name;
  if (!this.name) {
    throw new Error('name is required');
  }

  this.peers = new Peers();
}

Channel.prototype.addSocket = function (s) {
  var p = new Peer(s, this);
  this.peers.forEach(connectPeer(p));
  this.peers.push(p);
  return p;
}

function connectPeer(sourcePeer) {
  return function (targetPeer) {
    var payload = JSON.stringify({
        action:  'connect',
        source:  sourcePeer.id,
        target:  targetPeer.id,
        payload: /* payload */ '',
      });
    targetPeer.send(payload);
  }
}

module.exports = Channel;<|endoftext|>